From dbb51fd1d0133b503871c30cc1a94f1d3d170348 Mon Sep 17 00:00:00 2001 From: Michael Zhang Date: Sun, 17 Jul 2022 22:26:11 -0500 Subject: [PATCH] Some basic conditionals - No terminator analysis yet --- examples/conditions.e0 | 10 ++------- src/codegen/llvm_ir/expr.rs | 20 ++++++++++++++--- src/codegen/llvm_ir/if_else.rs | 41 ++++++++++++++++++++++++++++++---- src/parser.lalrpop | 2 +- 4 files changed, 57 insertions(+), 16 deletions(-) diff --git a/examples/conditions.e0 b/examples/conditions.e0 index 08cf616..67b4476 100644 --- a/examples/conditions.e0 +++ b/examples/conditions.e0 @@ -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; } diff --git a/src/codegen/llvm_ir/expr.rs b/src/codegen/llvm_ir/expr.rs index 7b776f8..b3514a8 100644 --- a/src/codegen/llvm_ir/expr.rs +++ b/src/codegen/llvm_ir/expr.rs @@ -44,13 +44,27 @@ impl LlvmIrCodegen { 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 {} {}, {}", diff --git a/src/codegen/llvm_ir/if_else.rs b/src/codegen/llvm_ir/if_else.rs index 701e433..4599703 100644 --- a/src/codegen/llvm_ir/if_else.rs +++ b/src/codegen/llvm_ir/if_else.rs @@ -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 LlvmIrCodegen { &mut self, if_else: &IfElse, ) -> 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(()) } } diff --git a/src/parser.lalrpop b/src/parser.lalrpop index a1db41b..5273b37 100644 --- a/src/parser.lalrpop +++ b/src/parser.lalrpop @@ -41,7 +41,7 @@ Expr: Expr<()> = { "(" ")" => expr, #[precedence(level = "0")] - r"[0-9]+" => Expr { kind: ExprKind::Int(<>.parse::().unwrap()), ty: () }, + r"-?[0-9]+" => Expr { kind: ExprKind::Int(<>.parse::().unwrap()), ty: () }, #[precedence(level = "0")] Ident => Expr { kind: ExprKind::Var(<>), ty: () },