Some basic conditionals
- No terminator analysis yet
This commit is contained in:
parent
090589fc3e
commit
dbb51fd1d0
4 changed files with 57 additions and 16 deletions
|
@ -5,13 +5,7 @@ fn main() -> int {
|
|||
return 10;
|
||||
} else if x > 50 {
|
||||
return 50;
|
||||
} else {
|
||||
if x < 20 {
|
||||
return 20;
|
||||
} else if x > 40 {
|
||||
return 40;
|
||||
} else {
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
return 65;
|
||||
}
|
||||
|
|
|
@ -44,13 +44,27 @@ impl<W: Write> LlvmIrCodegen<W> {
|
|||
None => bail!("Invalid types on operation."),
|
||||
};
|
||||
|
||||
let common_ty = type_to_llvm(&left.ty);
|
||||
let left = self.convert_expr(left)?;
|
||||
|
||||
let right = self.convert_expr(right)?;
|
||||
|
||||
match op {
|
||||
Op::LessThan => todo!(),
|
||||
Op::GreaterThan => todo!(),
|
||||
Op::LessThan => writeln!(
|
||||
self.writer,
|
||||
"{} = icmp slt {} {}, {}",
|
||||
expr_ref,
|
||||
common_ty,
|
||||
left.as_str(),
|
||||
right.as_str(),
|
||||
)?,
|
||||
Op::GreaterThan => writeln!(
|
||||
self.writer,
|
||||
"{} = icmp sgt {} {}, {}",
|
||||
expr_ref,
|
||||
common_ty,
|
||||
left.as_str(),
|
||||
right.as_str(),
|
||||
)?,
|
||||
Op::Plus => writeln!(
|
||||
self.writer,
|
||||
"{} = add {} {}, {}",
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::io::Write;
|
|||
|
||||
use anyhow::Result;
|
||||
|
||||
use crate::ast::{IfElse, Stmt, Type};
|
||||
use crate::ast::{ElseClause, IfElse, Stmt, Type};
|
||||
|
||||
use super::LlvmIrCodegen;
|
||||
|
||||
|
@ -11,9 +11,42 @@ impl<W: Write> LlvmIrCodegen<W> {
|
|||
&mut self,
|
||||
if_else: &IfElse<Type>,
|
||||
) -> Result<()> {
|
||||
// Build condition
|
||||
let cond = self.convert_expr(&if_else.cond);
|
||||
// Use a common identifier so they have the same number
|
||||
let cond = self.gensym(None, "cond");
|
||||
let success_label = format!("{cond}.success");
|
||||
let fail_label = format!("{cond}.fail");
|
||||
let exit_label = format!("{cond}.exit");
|
||||
|
||||
todo!()
|
||||
// Build condition
|
||||
let cond = self.convert_expr(&if_else.cond)?;
|
||||
writeln!(
|
||||
self.writer,
|
||||
"br i1 {}, label %{}, label %{}",
|
||||
cond.as_str(),
|
||||
success_label,
|
||||
fail_label
|
||||
)?;
|
||||
|
||||
// If true
|
||||
writeln!(self.writer, "{}:", success_label)?;
|
||||
self.convert_stmts(&if_else.body)?;
|
||||
writeln!(self.writer, "br label %{}", exit_label)?;
|
||||
|
||||
// If false
|
||||
writeln!(self.writer, "{}:", fail_label)?;
|
||||
match &if_else.else_clause {
|
||||
Some(ElseClause::If(if_else2)) => self.convert_if_else(if_else2)?,
|
||||
Some(ElseClause::Body(body)) => self.convert_stmts(body)?,
|
||||
None => {}
|
||||
}
|
||||
writeln!(self.writer, "br label %{}", exit_label)?;
|
||||
|
||||
// Exit branch
|
||||
writeln!(self.writer, "{}:", exit_label)?;
|
||||
// No-op in case this is the last statement
|
||||
let nop = self.gensym(Some("%"), "nop");
|
||||
writeln!(self.writer, "{nop} = add i1 0, 0")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ Expr: Expr<()> = {
|
|||
"(" <expr:Expr> ")" => expr,
|
||||
|
||||
#[precedence(level = "0")]
|
||||
r"[0-9]+" => Expr { kind: ExprKind::Int(<>.parse::<i64>().unwrap()), ty: () },
|
||||
r"-?[0-9]+" => Expr { kind: ExprKind::Int(<>.parse::<i64>().unwrap()), ty: () },
|
||||
|
||||
#[precedence(level = "0")]
|
||||
Ident => Expr { kind: ExprKind::Var(<>), ty: () },
|
||||
|
|
Loading…
Reference in a new issue