mirror of
https://github.com/Noratrieb/crapderive.git
synced 2026-01-16 17:45:07 +01:00
labels
This commit is contained in:
parent
4037fadd51
commit
c5e0e50989
1 changed files with 65 additions and 18 deletions
83
src/ir.rs
83
src/ir.rs
|
|
@ -47,7 +47,7 @@ pub enum Stmt {
|
||||||
struct CompileCtx {
|
struct CompileCtx {
|
||||||
stmts: Vec<Stmt>,
|
stmts: Vec<Stmt>,
|
||||||
spans: Vec<Span>,
|
spans: Vec<Span>,
|
||||||
labels: HashMap<String, usize>,
|
labels: HashMap<String, (Location, Span)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CompileCtx {
|
impl CompileCtx {
|
||||||
|
|
@ -59,48 +59,55 @@ impl CompileCtx {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile_stmt(&mut self, p_stmt: parser::Stmt) -> Result<()> {
|
fn compile_stmt(&mut self, p_stmt: parser::Stmt) -> Result<()> {
|
||||||
match p_stmt.kind {
|
let stmt = match p_stmt.kind {
|
||||||
StmtKind::Mov { from, to } => {
|
StmtKind::Mov { from, to } => {
|
||||||
let from = self.compile_value(from)?;
|
let from = self.compile_value(from)?;
|
||||||
let to = self.compile_place(to)?;
|
let to = self.compile_place(to)?;
|
||||||
let stmt = Stmt::Mov { from, to };
|
Stmt::Mov { from, to }
|
||||||
self.stmts.push(stmt);
|
|
||||||
}
|
}
|
||||||
StmtKind::Add { to, value } => {
|
StmtKind::Add { to, value } => {
|
||||||
let to = self.compile_place(to)?;
|
let to = self.compile_place(to)?;
|
||||||
let value = self.compile_value(value)?;
|
let value = self.compile_value(value)?;
|
||||||
let stmt = Stmt::Add { to, value };
|
Stmt::Add { to, value }
|
||||||
self.stmts.push(stmt);
|
|
||||||
}
|
}
|
||||||
StmtKind::Sub { to, value } => {
|
StmtKind::Sub { to, value } => {
|
||||||
let to = self.compile_place(to)?;
|
let to = self.compile_place(to)?;
|
||||||
let value = self.compile_value(value)?;
|
let value = self.compile_value(value)?;
|
||||||
let stmt = Stmt::Sub { to, value };
|
Stmt::Sub { to, value }
|
||||||
self.stmts.push(stmt);
|
|
||||||
}
|
}
|
||||||
StmtKind::Mul { to, value } => {
|
StmtKind::Mul { to, value } => {
|
||||||
let to = self.compile_place(to)?;
|
let to = self.compile_place(to)?;
|
||||||
let value = self.compile_value(value)?;
|
let value = self.compile_value(value)?;
|
||||||
let stmt = Stmt::Mul { to, value };
|
Stmt::Mul { to, value }
|
||||||
self.stmts.push(stmt);
|
|
||||||
}
|
}
|
||||||
StmtKind::Div { to, value } => {
|
StmtKind::Div { to, value } => {
|
||||||
let to = self.compile_place(to)?;
|
let to = self.compile_place(to)?;
|
||||||
let value = self.compile_value(value)?;
|
let value = self.compile_value(value)?;
|
||||||
let stmt = Stmt::Div { to, value };
|
Stmt::Div { to, value }
|
||||||
self.stmts.push(stmt);
|
}
|
||||||
|
StmtKind::Jmp { to } => {
|
||||||
|
let to = self.compile_location(to)?;
|
||||||
|
Stmt::Jmp { to }
|
||||||
|
}
|
||||||
|
StmtKind::Je { to } => {
|
||||||
|
let to = self.compile_location(to)?;
|
||||||
|
Stmt::Je { to }
|
||||||
}
|
}
|
||||||
StmtKind::Jmp { .. } => todo!("jmp"),
|
|
||||||
StmtKind::Je { .. } => todo!("je"),
|
|
||||||
StmtKind::Cmp { lhs, rhs } => {
|
StmtKind::Cmp { lhs, rhs } => {
|
||||||
let lhs = self.compile_value(lhs)?;
|
let lhs = self.compile_value(lhs)?;
|
||||||
let rhs = self.compile_value(rhs)?;
|
let rhs = self.compile_value(rhs)?;
|
||||||
let stmt = Stmt::Cmp { lhs, rhs };
|
Stmt::Cmp { lhs, rhs }
|
||||||
|
}
|
||||||
|
StmtKind::Label { name } => {
|
||||||
|
self.compile_label(name, p_stmt.span)?;
|
||||||
|
// no statement to emit here
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
self.stmts.push(stmt);
|
self.stmts.push(stmt);
|
||||||
}
|
|
||||||
StmtKind::Label { .. } => {}
|
|
||||||
}
|
|
||||||
self.spans.push(p_stmt.span);
|
self.spans.push(p_stmt.span);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -135,6 +142,46 @@ impl CompileCtx {
|
||||||
_ => Ok(Value::Place(self.compile_place(expr)?)),
|
_ => Ok(Value::Place(self.compile_place(expr)?)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_label_position(&self, label: &str, span: Span) -> Result<Location> {
|
||||||
|
let location = self.labels.get(label);
|
||||||
|
location
|
||||||
|
.map(|(location,_)| *location)
|
||||||
|
.ok_or_else(|| CompilerError::simple(format!("label `{label}` not found"), span))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compile_location(&mut self, expr: parser::Expr) -> Result<Location> {
|
||||||
|
match expr.kind {
|
||||||
|
ExprKind::Symbol(sym) => Ok(self.get_label_position(&sym, expr.span)?),
|
||||||
|
ExprKind::Register(_) => Err(CompilerError::simple(
|
||||||
|
"cannot jump to a register".to_string(),
|
||||||
|
expr.span,
|
||||||
|
)),
|
||||||
|
ExprKind::Number(_) => Err(CompilerError::simple(
|
||||||
|
"cannot jump to a number literal".to_string(),
|
||||||
|
expr.span,
|
||||||
|
)),
|
||||||
|
ExprKind::Addr(_) => Err(CompilerError::simple(
|
||||||
|
"cannot jump to a dereferenced address".to_string(),
|
||||||
|
expr.span,
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compile_label(&mut self, label: String, span: Span) -> Result<()> {
|
||||||
|
let index = self.stmts.len();
|
||||||
|
let old = self
|
||||||
|
.labels
|
||||||
|
.insert(label, (Location { index }, span.clone()));
|
||||||
|
if let Some((_, old_span)) = old {
|
||||||
|
return Err(CompilerError::new_notes(
|
||||||
|
"duplicate label found".to_string(),
|
||||||
|
span,
|
||||||
|
vec![("previous label defined here".to_string(), old_span)],
|
||||||
|
));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compile(ast: impl Iterator<Item = parser::Stmt>) -> Result<(Vec<Stmt>, Vec<Span>)> {
|
pub fn compile(ast: impl Iterator<Item = parser::Stmt>) -> Result<(Vec<Stmt>, Vec<Span>)> {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue