diff --git a/src/CodeGen/compilation/assign.rs b/src/CodeGen/compilation/assign.rs index 3bcce65b..45259632 100644 --- a/src/CodeGen/compilation/assign.rs +++ b/src/CodeGen/compilation/assign.rs @@ -30,7 +30,7 @@ impl CompilationHelper { #[allow(missing_docs)] pub fn compile_assign_var_var(&mut self, node: &Assign, mc_sink: &mut Vec, block: &Block) { - let src1 = *self.vars.get(&node.inner2).expect(&format!("{} has no variable location", node.inner2)); + let src1 = *self.vars.get(&node.inner2.name).expect(&format!("{} has no variable location", node.inner2)); let boxed: Box = Box::new(node.clone()); diff --git a/src/CodeGen/compilation/br.rs b/src/CodeGen/compilation/br.rs index 0783ef79..890ec6ed 100644 --- a/src/CodeGen/compilation/br.rs +++ b/src/CodeGen/compilation/br.rs @@ -27,7 +27,7 @@ impl CompilationHelper { self.free(&node.inner1); } - let src = *self.vars.get(&node.inner1).expect("expected valid variable"); + let src = *self.vars.get(&node.inner1.name).expect("expected valid variable"); let src = match src { super::VarLocation::Reg(reg) => MachineOperand::Reg(reg), diff --git a/src/CodeGen/compilation/call.rs b/src/CodeGen/compilation/call.rs index 6e72cfa4..f83a54c8 100644 --- a/src/CodeGen/compilation/call.rs +++ b/src/CodeGen/compilation/call.rs @@ -23,7 +23,7 @@ impl CompilationHelper { todo!("implemt arguments which are passed over the stack"); } - let src = self.vars.get(arg).expect("expected valid variable"); + let src = self.vars.get(&arg.name).expect("expected valid variable"); match src { VarLocation::Reg(reg) => instr.add_operand(MachineOperand::Reg(*reg)), diff --git a/src/CodeGen/compilation/cast.rs b/src/CodeGen/compilation/cast.rs index a68d1e83..72f1dd33 100644 --- a/src/CodeGen/compilation/cast.rs +++ b/src/CodeGen/compilation/cast.rs @@ -6,7 +6,7 @@ use crate::CodeGen::{MachineInstr, MachineMnemonic, MachineOperand}; impl CompilationHelper { #[allow(missing_docs)] pub fn compile_cast(&mut self, node: &Cast, mc_sink: &mut Vec, block: &Block) { - let src1 = *self.vars.get(&node.inner1).expect("expected valid variable"); + let src1 = *self.vars.get(&node.inner1.name).expect("expected valid variable"); let boxed: Box = Box::new(node.clone()); diff --git a/src/CodeGen/compilation/math.rs b/src/CodeGen/compilation/math.rs index 12609fb3..56cdb079 100644 --- a/src/CodeGen/compilation/math.rs +++ b/src/CodeGen/compilation/math.rs @@ -8,8 +8,8 @@ macro_rules! MathVarVar { impl CompilationHelper { #[allow(missing_docs)] pub(crate) fn $func(&mut self, node: &$node, mc_sink: &mut Vec, block: &Block) { - let src1 = *self.vars.get(&node.inner1).expect("expected valid variable"); - let src2 = *self.vars.get(&node.inner2).expect("expected valid variable"); + let src1 = *self.vars.get(&node.inner1.name).expect("expected valid variable"); + let src2 = *self.vars.get(&node.inner2.name).expect("expected valid variable"); let boxed: Box = Box::new(node.clone()); @@ -62,7 +62,7 @@ macro_rules! MathVarType { impl CompilationHelper { #[allow(missing_docs)] pub fn $func(&mut self, node: &$node, mc_sink: &mut Vec, block: &Block) { - let src1 = *self.vars.get(&node.inner1).expect("expected valid variable"); + let src1 = *self.vars.get(&node.inner1.name).expect("expected valid variable"); let boxed: Box = Box::new(node.clone()); diff --git a/src/CodeGen/compilation/mod.rs b/src/CodeGen/compilation/mod.rs index 90e9f15f..77af00fe 100644 --- a/src/CodeGen/compilation/mod.rs +++ b/src/CodeGen/compilation/mod.rs @@ -19,7 +19,7 @@ pub struct CompilationHelper { pub(crate) call: MachineCallingConvention, - pub(crate) vars: HashMap, + pub(crate) vars: HashMap, } impl CompilationHelper { @@ -35,7 +35,7 @@ impl CompilationHelper { /// frees the resources of the variable pub(crate) fn free(&mut self, var: &Var) { - if let Some(location) = self.vars.get(var) { + if let Some(location) = self.vars.get(&var.name) { match location { VarLocation::Reg(reg) => self.regs.push(reg.arch(), reg.clone()), } @@ -52,7 +52,7 @@ impl CompilationHelper { todo!("Registers ran out. And memory variables are currently not implemented") }; - self.vars.insert(var.clone(), location); + self.vars.insert(var.name.to_owned(), location); location } @@ -75,7 +75,7 @@ impl CompilationHelper { }; self.vars.insert( - func.arg(num), + func.arg(num).name, location ); diff --git a/src/CodeGen/compilation/ret.rs b/src/CodeGen/compilation/ret.rs index 98cbe34f..db46a1f6 100644 --- a/src/CodeGen/compilation/ret.rs +++ b/src/CodeGen/compilation/ret.rs @@ -17,7 +17,7 @@ impl CompilationHelper { #[allow(missing_docs)] pub fn compile_ret_var(&mut self, node: &Return, mc_sink: &mut Vec, _: &Block) { - let src = *self.vars.get(&node.inner1).expect("expected valid variable"); + let src = *self.vars.get(&node.inner1.name).expect("expected valid variable"); let mut instr = MachineInstr::new(MachineMnemonic::Move); diff --git a/src/IR/nodes/br.rs b/src/IR/nodes/br.rs index 22cc592b..db7a84d1 100644 --- a/src/IR/nodes/br.rs +++ b/src/IR/nodes/br.rs @@ -73,6 +73,14 @@ impl Ir for BrCond { fn compile(&self, registry: &mut crate::Target::TargetBackendDescr) { registry.compile_br_cond(self) } + + fn uses(&self, var: &Var) -> bool { + if self.inner1.name.to_owned() == var.name.to_owned() { + true + } else { + false + } + } } /// This trait is used for building br nodes diff --git a/src/IR/parser/lexer.rs b/src/IR/parser/lexer.rs index bdcba1e8..d67f8919 100644 --- a/src/IR/parser/lexer.rs +++ b/src/IR/parser/lexer.rs @@ -75,6 +75,9 @@ pub enum TokenType { /// block: Block(String), + + /// cond + Cond, } impl TokenType { @@ -99,6 +102,7 @@ impl TokenType { TokenType::Func(_) => "func", TokenType::TripleDot => "...", TokenType::Block(_) => "block", + TokenType::Cond => "cond", }.to_string() } } @@ -145,6 +149,7 @@ impl IrLexer { keys.insert("declare".into(), TokenType::Declare); keys.insert("define".into(), TokenType::Define); keys.insert("const".into(), TokenType::Const); + keys.insert("cond".into(), TokenType::Cond); let lines = input diff --git a/src/IR/parser/parser.rs b/src/IR/parser/parser.rs index fdd7429c..9804d939 100644 --- a/src/IR/parser/parser.rs +++ b/src/IR/parser/parser.rs @@ -558,19 +558,67 @@ impl IrParser { fn parse_br(&mut self) -> Result, IrError> { self.input.pop_front(); // br - self.expect( TokenType::Ident(String::new()) )?; // block names are idents - - let block = if let TokenType::Ident(name) = &self.current_token()?.typ { - name.to_owned() - } else { unreachable!() }; + let current = self.current_token()?; - self.input.pop_front(); + match ¤t.typ { + TokenType::Ident(block) => { + let block = block.to_owned(); + + self.input.pop_front(); + + Ok(ir::Br::new(Box::from(Block { + name: block, + nodes: vec![], + varCount: 0 + }))) + }, + TokenType::Cond => { + self.input.pop_front(); // cond + + let var = self.expect(TokenType::Var(String::new()))?; + + let var = if let TokenType::Var(var) = var.typ + { var } else { unreachable!() }; + + self.input.pop_front(); + + self.expect(TokenType::Ident(String::new()))?; + + let iftrue; - Ok(ir::Br::new(Box::from(Block { - name: block, - nodes: vec![], - varCount: 0 - }))) + if let TokenType::Ident(ident) = &self.current_token()?.typ { + iftrue = ident.to_owned(); + } else { unreachable!() } + + self.input.pop_front(); + + self.expect(TokenType::Comma)?; + self.input.pop_front(); + + self.expect(TokenType::Ident(String::new()))?; + + let iffalse; + + if let TokenType::Ident(ident) = &self.current_token()?.typ { + iffalse = ident.to_owned(); + } else { unreachable!() } + self.input.pop_front(); + + Ok(ir::BrCond::new(Var { + name: var, + ty: TypeMetadata::Void, + }, Block { + name: iftrue, + nodes: vec![], + varCount: 0, + }, Block { + name: iffalse, + nodes: vec![], + varCount: 0, + })) + }, + _ => Err(IrError::UnexpectedToken(self.current_token()?.clone())), + } } fn parse_cast(&mut self, var: String) -> Result, IrError> { diff --git a/src/IR/parser/semnatic.rs b/src/IR/parser/semnatic.rs index 912d6270..cc4ed503 100644 --- a/src/IR/parser/semnatic.rs +++ b/src/IR/parser/semnatic.rs @@ -183,6 +183,8 @@ impl<'a> IrSemnatic<'a> { self.analaysiz_div_var_var(&mut vars, node, loc)?; } else if let Some(node) = any.downcast_ref::>() { self.analaysiz_cast(&mut vars, node, loc)?; + } else if let Some(node) = any.downcast_ref::>() { + self.analaysiz_br_cond(func, &mut vars, node, loc)?; } } } @@ -388,6 +390,36 @@ impl<'a> IrSemnatic<'a> { Ok(()) } + fn analaysiz_br_cond(&mut self, func: &String, vars: &mut HashMap, node: &BrCond, loc: Loc) -> Result<(), IrError> { + let (_, _, blocks) = self.func_sigs.get(func).unwrap(); + + if !blocks.contains(&node.inner2.name) { + Err(IrError::Unkown { + what: "block".to_owned(), + name: node.inner2.name.to_owned(), + loc: loc.to_owned() + })? + } + + if !blocks.contains(&node.inner3.name) { + Err(IrError::Unkown { + what: "block".to_owned(), + name: node.inner3.name.to_owned(), + loc: loc.to_owned() + })? + } + + if !vars.contains_key(&node.inner1.name) { + Err(IrError::Unkown { + what: "variable".to_owned(), + name: node.inner1.name.to_owned(), + loc: loc + })? + } + + Ok(()) + } + fn analyize_const(&mut self, _: &String, _: &Vec, _: &Loc, _: Linkage) -> Result<(), IrError> { Ok(()) // what can go wrong on constants? } diff --git a/tests/IR/br.yl b/tests/IR/br0.yl similarity index 100% rename from tests/IR/br.yl rename to tests/IR/br0.yl diff --git a/tests/IR/br1.yl b/tests/IR/br1.yl new file mode 100644 index 00000000..dab165a0 --- /dev/null +++ b/tests/IR/br1.yl @@ -0,0 +1,18 @@ +# RUN: +cargo run -p ylc -- -in=%s -o=out.o +gcc out.o -o a.exe +./a.exe +# IN: +define u32 @main() { + entry: + %1 = u64 1 + br cond %1 istrue, isfalse + + istrue: + ret u32 235 + + isfalse: + ret u32 54 +} + +# EXIT_CODE=235