From 547769ade46cd300f43f21505b53481556cd14aa Mon Sep 17 00:00:00 2001 From: TheCPP Date: Sun, 24 Nov 2024 10:07:13 +0100 Subject: [PATCH] [YCC] ycc is now able to compile ifs --- src/IR/func.rs | 27 +++++++ src/IR/nodes/alloca.rs | 2 +- src/IR/nodes/assign.rs | 6 +- src/IR/nodes/br.rs | 4 +- src/IR/nodes/call.rs | 2 +- src/IR/nodes/cast.rs | 4 +- src/IR/nodes/cmp.rs | 8 +-- src/IR/nodes/debug.rs | 2 +- src/IR/nodes/getelemptr.rs | 2 +- src/IR/nodes/load.rs | 2 +- src/IR/nodes/math.rs | 8 +-- src/IR/nodes/neg.rs | 2 +- src/IR/nodes/phi.rs | 2 +- src/IR/nodes/ret.rs | 4 +- src/IR/nodes/select.rs | 8 +-- src/IR/nodes/store.rs | 4 +- src/IR/nodes/switch.rs | 2 +- src/IR/parser/gen.rs | 1 + tools/ycc/src/ast.rs | 140 ------------------------------------ tools/ycc/src/codegen.rs | 141 +++++++++++++++++++++++++++++++------ tools/ycc/src/main.rs | 34 +++++++-- tools/ycc/src/utils.rs | 31 +++----- 22 files changed, 214 insertions(+), 222 deletions(-) delete mode 100644 tools/ycc/src/ast.rs diff --git a/src/IR/func.rs b/src/IR/func.rs index e1632c3b..98009e89 100644 --- a/src/IR/func.rs +++ b/src/IR/func.rs @@ -63,6 +63,8 @@ pub struct Function { pub(crate) linkage: Linkage, pub(crate) blocks: VecDeque, + + pub(crate) curr_block: usize, } impl Function { @@ -76,6 +78,8 @@ impl Function { name: name, linkage: Linkage::Internal, + + curr_block: 0, } } @@ -97,9 +101,32 @@ impl Function { /// Adds a new block to the function pub fn addBlock(&mut self, name: &str) -> BlockId { self.blocks.push_back(Block::new(name, &self)); + self.curr_block = self.blocks.len() - 1; BlockId(name.to_owned()) } + /// Returns the current block + pub fn currentBlock(&self) -> BlockId { + let curr_block = self.blocks.back().expect("expected current block"); + let name = curr_block.name.to_owned(); + + BlockId(name) + } + + /// Sets the current block (Time: `O(n)`) + pub fn setCurrBlock(&mut self, curr_block: BlockId) { + let mut index = 0; + + for block in &self.blocks { + if block.name == curr_block.name { + self.curr_block = index; + break; + } + + index += 1; + } + } + /// Emits the Ir of the function into a string pub fn dump(&self) -> String { if self.linkage == Linkage::Extern { diff --git a/src/IR/nodes/alloca.rs b/src/IR/nodes/alloca.rs index b7b02057..4bd2f828 100644 --- a/src/IR/nodes/alloca.rs +++ b/src/IR/nodes/alloca.rs @@ -74,7 +74,7 @@ impl Alloca { impl Function { /// Builds an stack allocation (the out var is the pointer to the allocated stack region) pub fn BuildAlloca(&mut self, ty: TypeMetadata) -> Var { - let block = self.blocks.back_mut().expect("the IRBuilder needs to have an current block\nConsider creating one"); + let block = self.blocks.get_mut(self.curr_block).expect("invalid current block"); let out = Var::new(block, TypeMetadata::ptr); diff --git a/src/IR/nodes/assign.rs b/src/IR/nodes/assign.rs index 9407804e..130bd72c 100644 --- a/src/IR/nodes/assign.rs +++ b/src/IR/nodes/assign.rs @@ -247,7 +247,7 @@ pub trait BuildAssign { } impl BuildAssign for Function { fn BuildAssign(&mut self, value: Type) -> Var { - let block = self.blocks.back_mut().expect("the IRBuilder needs to have an current block\nConsider creating one"); + let block = self.blocks.get_mut(self.curr_block).expect("invalid current block"); let out = Var::new(block, value.into()); @@ -259,7 +259,7 @@ impl BuildAssign for Function { impl BuildAssign for Function { fn BuildAssign(&mut self, value: Var) -> Var { - let block = self.blocks.back_mut().expect("the IRBuilder needs to have an current block\nConsider creating one"); + let block = self.blocks.get_mut(self.curr_block).expect("invalid current block"); let out = Var::new(block, value.ty); @@ -271,7 +271,7 @@ impl BuildAssign for Function { impl BuildAssign<&Const> for Function { fn BuildAssign(&mut self, value: &Const) -> Var { - let block = self.blocks.back_mut().expect("the IRBuilder needs to have an current block\nConsider creating one"); + let block = self.blocks.get_mut(self.curr_block).expect("invalid current block"); let out = Var::new(block, TypeMetadata::ptr); diff --git a/src/IR/nodes/br.rs b/src/IR/nodes/br.rs index 88e6e237..3642dd41 100644 --- a/src/IR/nodes/br.rs +++ b/src/IR/nodes/br.rs @@ -182,7 +182,7 @@ pub trait BuildBr { impl BuildBr<&BlockId> for Function { fn BuildBr(&mut self, to: &BlockId) { - let block = self.blocks.back_mut().expect("the IRBuilder needs to have an current block\nConsider creating one"); + let block = self.blocks.get_mut(self.curr_block).expect("invalid current block"); block.push_ir(Br::new( to.to_owned() )); } @@ -198,7 +198,7 @@ pub trait BuildBrCond { impl BuildBrCond for Function { fn BuildBrCond(&mut self, val: Var, iftrue: &BlockId, iffalse: &BlockId) { - let block = self.blocks.back_mut().expect("the IRBuilder needs to have an current block\nConsider creating one"); + let block = self.blocks.get_mut(self.curr_block).expect("invalid current block"); block.push_ir( BrCond::new(val, iftrue.to_owned(), iffalse.to_owned())); } diff --git a/src/IR/nodes/call.rs b/src/IR/nodes/call.rs index cad31170..a01afade 100644 --- a/src/IR/nodes/call.rs +++ b/src/IR/nodes/call.rs @@ -154,7 +154,7 @@ pub trait BuildCall { } impl BuildCall<&FuncId, Vec> for Function { fn BuildCall(&mut self, func: &FuncId, args: Vec) -> Var { - let block = self.blocks.back_mut().expect("the IRBuilder needs to have an current block\nConsider creating one"); + let block = self.blocks.get_mut(self.curr_block).expect("invalid current block"); let out = Var::new(block, func.ty.ret); diff --git a/src/IR/nodes/cast.rs b/src/IR/nodes/cast.rs index 1209dbb3..b0f7adfc 100644 --- a/src/IR/nodes/cast.rs +++ b/src/IR/nodes/cast.rs @@ -144,7 +144,7 @@ pub trait BuildCast { impl BuildCast for Function { fn BuildCast(&mut self, var: Var, ty: TypeMetadata) -> Var { - let block = self.blocks.back_mut().expect("the IRBuilder needs to have an current block\nConsider creating one"); + let block = self.blocks.get_mut(self.curr_block).expect("invalid current block"); let out = Var::new(block, ty); @@ -156,7 +156,7 @@ impl BuildCast for Function { impl BuildCast for Function { fn BuildCast(&mut self, value: Type, ty: TypeMetadata) -> Var { - let block = self.blocks.back_mut().expect("the IRBuilder needs to have an current block\nConsider creating one"); + let block = self.blocks.get_mut(self.curr_block).expect("invalid current block"); let out = Var::new(block, ty); diff --git a/src/IR/nodes/cmp.rs b/src/IR/nodes/cmp.rs index 50d27aee..6505f3f2 100644 --- a/src/IR/nodes/cmp.rs +++ b/src/IR/nodes/cmp.rs @@ -218,7 +218,7 @@ pub trait BuildCmp { impl BuildCmp for Function { fn BuildCmp(&mut self, mode: CmpMode, ls: Var, rs: Var) -> Var { - let block = self.blocks.back_mut().expect("the IRBuilder needs to have an current block\nConsider creating one"); + let block = self.blocks.get_mut(self.curr_block).expect("invalid current block"); let out = Var::new(block, TypeMetadata::u8); @@ -230,7 +230,7 @@ impl BuildCmp for Function { impl BuildCmp for Function { fn BuildCmp(&mut self, mode: CmpMode, ls: Var, rs: Type) -> Var { - let block = self.blocks.back_mut().expect("the IRBuilder needs to have an current block\nConsider creating one"); + let block = self.blocks.get_mut(self.curr_block).expect("invalid current block"); let out = Var::new(block, TypeMetadata::u8); @@ -242,7 +242,7 @@ impl BuildCmp for Function { impl BuildCmp for Function { fn BuildCmp(&mut self, mode: CmpMode, ls: Type, rs: Var) -> Var { - let block = self.blocks.back_mut().expect("the IRBuilder needs to have an current block\nConsider creating one"); + let block = self.blocks.get_mut(self.curr_block).expect("invalid current block"); let out = Var::new(block, TypeMetadata::u8); @@ -254,7 +254,7 @@ impl BuildCmp for Function { impl BuildCmp for Function { fn BuildCmp(&mut self, mode: CmpMode, ls: Type, rs: Type) -> Var { - let block = self.blocks.back_mut().expect("the IRBuilder needs to have an current block\nConsider creating one"); + let block = self.blocks.get_mut(self.curr_block).expect("invalid current block"); let out = Var::new(block, TypeMetadata::u8); diff --git a/src/IR/nodes/debug.rs b/src/IR/nodes/debug.rs index fc1ff6e5..098ec593 100644 --- a/src/IR/nodes/debug.rs +++ b/src/IR/nodes/debug.rs @@ -82,7 +82,7 @@ impl IsNode for DebugNode { impl Function { /// Sets the source location for debugging (all of the ir nodes will respond to the location till an new location is set) pub fn BuildDebug(&mut self, line: i64, coloumn: i64, file: PathBuf) { - let block = self.blocks.back_mut().expect("the IRBuilder needs to have an current block\nConsider creating one"); + let block = self.blocks.get_mut(self.curr_block).expect("invalid current block"); block.push_ir( Box::new( DebugNode { line: line, diff --git a/src/IR/nodes/getelemptr.rs b/src/IR/nodes/getelemptr.rs index 58aa39ff..d1178484 100644 --- a/src/IR/nodes/getelemptr.rs +++ b/src/IR/nodes/getelemptr.rs @@ -107,7 +107,7 @@ impl Function { /// } /// ``` pub fn BuildGetelemptr(&mut self, var: Var, index: Var, ty: TypeMetadata) -> Var { - let block = self.blocks.back_mut().expect("expected current block"); + let block = self.blocks.get_mut(self.curr_block).expect("invalid current block"); let out = Var::new(block, ty); diff --git a/src/IR/nodes/load.rs b/src/IR/nodes/load.rs index 938251b8..02f0a04b 100644 --- a/src/IR/nodes/load.rs +++ b/src/IR/nodes/load.rs @@ -78,7 +78,7 @@ impl EvalOptVisitor for Load { impl Function { /// the load instruction loads an value from an pointer into a normal variable pub fn BuildLoad(&mut self, ptr: Var, ty: TypeMetadata) -> Var { - let block = self.blocks.back_mut().expect("the IRBuilder needs to have an current block\nConsider creating one"); + let block = self.blocks.get_mut(self.curr_block).expect("invalid current block"); let out = Var::new(block, ty); diff --git a/src/IR/nodes/math.rs b/src/IR/nodes/math.rs index 48ec5988..09e08577 100644 --- a/src/IR/nodes/math.rs +++ b/src/IR/nodes/math.rs @@ -10,7 +10,7 @@ macro_rules! MathIrNode { impl $build_trait for Function { fn $build_func(&mut self, op0: Type, op1: Type) -> Var { - let block = self.blocks.back_mut().expect("the IRBuilder needs to have an current block\nConsider creating one"); + let block = self.blocks.get_mut(self.curr_block).expect("invalid current block"); let op0Ty: TypeMetadata = op0.into(); @@ -25,7 +25,7 @@ macro_rules! MathIrNode { impl $build_trait for Function { fn $build_func(&mut self, op0: Var, op1: Type) -> Var { - let block = self.blocks.back_mut().expect("the IRBuilder needs to have an current block\nConsider creating one"); + let block = self.blocks.get_mut(self.curr_block).expect("invalid current block"); let op0Ty: TypeMetadata = op0.ty.into(); @@ -40,7 +40,7 @@ macro_rules! MathIrNode { impl $build_trait for Function { fn $build_func(&mut self, op0: Type, op1: Var) -> Var { - let block = self.blocks.back_mut().expect("the IRBuilder needs to have an current block\nConsider creating one"); + let block = self.blocks.get_mut(self.curr_block).expect("invalid current block"); let op0Ty: TypeMetadata = op0.into(); @@ -55,7 +55,7 @@ macro_rules! MathIrNode { impl $build_trait for Function { fn $build_func(&mut self, op0: Var, op1: Var) -> Var { - let block = self.blocks.back_mut().expect("the IRBuilder needs to have an current block\nConsider creating one"); + let block = self.blocks.get_mut(self.curr_block).expect("invalid current block"); let op0Ty: TypeMetadata = op0.ty.into(); diff --git a/src/IR/nodes/neg.rs b/src/IR/nodes/neg.rs index a9722194..9fc51352 100644 --- a/src/IR/nodes/neg.rs +++ b/src/IR/nodes/neg.rs @@ -78,7 +78,7 @@ impl Function { panic!("variables need to be signed to get negated"); } - let block = self.blocks.back_mut().expect("expects current block"); + let block = self.blocks.get_mut(self.curr_block).expect("invalid current block"); let out = Var::new(block, var.ty); diff --git a/src/IR/nodes/phi.rs b/src/IR/nodes/phi.rs index 355ca8e3..222064d5 100644 --- a/src/IR/nodes/phi.rs +++ b/src/IR/nodes/phi.rs @@ -104,7 +104,7 @@ impl IsNode for Phi { impl Function { /// Builds the phi node which recives variables from different blocks pub fn BuildPhi(&mut self, typ: TypeMetadata, recipients: Vec<(&Block, Var)>) -> Var { - let block = self.blocks.back_mut().expect("expected valid current block.\nConsider creating one"); + let block = self.blocks.get_mut(self.curr_block).expect("invalid current block"); let mut owned_recipients = Vec::new(); diff --git a/src/IR/nodes/ret.rs b/src/IR/nodes/ret.rs index e6415cd0..608ea0d2 100644 --- a/src/IR/nodes/ret.rs +++ b/src/IR/nodes/ret.rs @@ -103,14 +103,14 @@ pub trait BuildReturn { impl BuildReturn for Function { fn BuildRet(&mut self, val: Type) { - self.blocks.back_mut().expect("the IRBuilder needs to have an current block\nConsider creating one") + self.blocks.get_mut(self.curr_block).expect("invalid current block") .push_ir(Return::new(IROperand::Type(val))) } } impl BuildReturn for Function { fn BuildRet(&mut self, var: Var) { - self.blocks.back_mut().expect("the IRBuilder needs to have an current block\nConsider creating one") + self.blocks.get_mut(self.curr_block).expect("invalid current block") .push_ir(Return::new(IROperand::Var(var))) } } \ No newline at end of file diff --git a/src/IR/nodes/select.rs b/src/IR/nodes/select.rs index fbe4455e..cbe3569d 100644 --- a/src/IR/nodes/select.rs +++ b/src/IR/nodes/select.rs @@ -236,7 +236,7 @@ pub trait BuildSelect { impl BuildSelect for Function { fn BuildSelect(&mut self, cond: Var, yes: Type, no: Type) -> Var { - let block = self.blocks.back_mut().expect("expected valid current block"); + let block = self.blocks.get_mut(self.curr_block).expect("invalid current block"); let out = Var::new(block, yes.into()); @@ -253,7 +253,7 @@ impl BuildSelect for Function { impl BuildSelect for Function { fn BuildSelect(&mut self, cond: Var, yes: Type, no: Var) -> Var { - let block = self.blocks.back_mut().expect("expected valid current block"); + let block = self.blocks.get_mut(self.curr_block).expect("invalid current block"); let out = Var::new(block, yes.into()); @@ -270,7 +270,7 @@ impl BuildSelect for Function { impl BuildSelect for Function { fn BuildSelect(&mut self, cond: Var, yes: Var, no: Type) -> Var { - let block = self.blocks.back_mut().expect("expected valid current block"); + let block = self.blocks.get_mut(self.curr_block).expect("invalid current block"); let out = Var::new(block, yes.ty); @@ -287,7 +287,7 @@ impl BuildSelect for Function { impl BuildSelect for Function { fn BuildSelect(&mut self, cond: Var, yes: Var, no: Var) -> Var { - let block = self.blocks.back_mut().expect("expected valid current block"); + let block = self.blocks.get_mut(self.curr_block).expect("invalid current block"); let out = Var::new(block, yes.ty); diff --git a/src/IR/nodes/store.rs b/src/IR/nodes/store.rs index f210d85e..57fd1229 100644 --- a/src/IR/nodes/store.rs +++ b/src/IR/nodes/store.rs @@ -103,7 +103,7 @@ pub trait BuildStore { impl BuildStore for Function { fn BuildStore(&mut self, target: Var, value: Var) { - let block = self.blocks.back_mut().expect("the IRBuilder needs to have an current block\nConsider creating one"); + let block = self.blocks.get_mut(self.curr_block).expect("invalid current block"); block.push_ir( Store::new(target, IROperand::Var(value)) ); } @@ -111,7 +111,7 @@ impl BuildStore for Function { impl BuildStore for Function { fn BuildStore(&mut self, target: Var, value: Type) { - let block = self.blocks.back_mut().expect("the IRBuilder needs to have an current block\nConsider creating one"); + let block = self.blocks.get_mut(self.curr_block).expect("invalid current block"); block.push_ir( Store::new(target, IROperand::Type(value)) ); } diff --git a/src/IR/nodes/switch.rs b/src/IR/nodes/switch.rs index 375597da..cfa63897 100644 --- a/src/IR/nodes/switch.rs +++ b/src/IR/nodes/switch.rs @@ -116,7 +116,7 @@ impl IsNode for Switch { impl Function { /// Builds an switch statement pub fn BuildSwitch(&mut self, source: Var, default: &BlockId, cases: HashMap) { - let block = self.blocks.back_mut().expect("expected current block"); + let block = self.blocks.get_mut(self.curr_block).expect("invalid current block"); let mut owned_cases = HashMap::new(); diff --git a/src/IR/parser/gen.rs b/src/IR/parser/gen.rs index eff05bcd..a0d56948 100644 --- a/src/IR/parser/gen.rs +++ b/src/IR/parser/gen.rs @@ -37,6 +37,7 @@ impl IrGen { name: name, linkage: scope, blocks: VecDeque::new(), + curr_block: 0, }; for (name, block) in body { diff --git a/tools/ycc/src/ast.rs b/tools/ycc/src/ast.rs deleted file mode 100644 index b791d11c..00000000 --- a/tools/ycc/src/ast.rs +++ /dev/null @@ -1,140 +0,0 @@ -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum Visibility { - Private, - Extern, - Static, -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum AstTypeMeta { - Void, - - Bool, - Char, - Short, - Int, - Long, - Float, - Double, - - Struct, - Enum -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct AstType { - pub meta: AstTypeMeta, - pub signed: bool, - pub unsigned: bool, -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum TopLevelStmt { - Func(FuncStmt), - Global(GlobalStmt), - Const(ConstStmt), - Enum(EnumStmt), - Struct(StructStmt), -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct FuncStmt { - pub name: String, - pub visibility: Visibility, - pub return_type: AstType, - pub args: Vec<(String, AstType)>, - pub body: Vec, - pub only_ty_indector: bool, -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct GlobalStmt { - pub name: String, - pub visibility: Visibility, - pub ty: AstType, - pub initializer: Option, -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct ConstStmt { - pub name: String, - pub visibility: Visibility, - pub ty: AstType, - pub initializer: Expr, -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct EnumStmt { - pub name: String, - pub values: Vec<(String, Option)>, -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct StructStmt { - pub name: String, - - pub fields: Vec<(String, AstType)>, -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum AstOperand { - Add, - Sub, - Mul, - Div, - Mod, - Xor, - Or, - And, - Shl, - Shr, - OrOr, - AndAnd, - Not, - BitwiseNot, -} - -#[derive(Debug, Clone)] -pub enum Expr { - Binary { - ls: Box, - op: AstOperand, - rs: Box, - }, - - IntLiteral(i64), - FloatLiteral(f64), - StringLiteral(String), - CharLiteral(char), - - Unary { - op: AstOperand, - expr: Box, - }, - - Var(String), -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum Stmt { - Return { - value: Expr, - }, - Block { - body: Vec - } -} - -impl PartialEq for Expr { - fn eq(&self, other: &Self) -> bool { - match (self, other) { - (Self::IntLiteral(l0), Self::IntLiteral(r0)) => l0 == r0, - (Self::FloatLiteral(l0), Self::FloatLiteral(r0)) => l0 == r0, - (Self::StringLiteral(l0), Self::StringLiteral(r0)) => l0 == r0, - (Self::CharLiteral(l0), Self::CharLiteral(r0)) => l0 == r0, - _ => false, - } - } -} - -impl Eq for Expr {} \ No newline at end of file diff --git a/tools/ycc/src/codegen.rs b/tools/ycc/src/codegen.rs index 203668dd..2c218df8 100644 --- a/tools/ycc/src/codegen.rs +++ b/tools/ycc/src/codegen.rs @@ -6,16 +6,16 @@ use ygen::{prelude::*, Target::Triple, IR::{FunctionType, Module, TypeMetadata}} /// Code generation using ygen pub struct CodeGeneration { src: Vec>, - triple: Triple, pub module: Module, + if_count: usize, } impl CodeGeneration { - pub fn new(src: Vec>, triple: Triple) -> Self { + pub fn new(src: Vec>) -> Self { Self { - src, - triple, + if_count: 0, + src: src, module: Module::new(), } } @@ -31,11 +31,33 @@ impl CodeGeneration { } fn gen_func(&mut self, node: Node) { - let ret = node.node.specifiers.get(0).expect("expected return type").node.clone(); - let ret: TypeWrapper = if let DeclarationSpecifier::TypeSpecifier(ty) = ret { - ty.node.into() - } else { panic!("{:?}", ret) }; - let ret: TypeMetadata = ret.into(); + let mut extrn = false; + let mut ret: Option = None; + + for specifier in node.node.specifiers { + let specifier = specifier.node; + + if let DeclarationSpecifier::StorageClass(storage_class) = &specifier { + let storage_class = &storage_class.node; + + match storage_class { + StorageClassSpecifier::Typedef => todo!(), + StorageClassSpecifier::Extern => extrn = true, + StorageClassSpecifier::Static => todo!(), + StorageClassSpecifier::ThreadLocal => todo!(), + StorageClassSpecifier::Auto => todo!(), + StorageClassSpecifier::Register => todo!(), + } + } + + if let DeclarationSpecifier::TypeSpecifier(ty) = specifier { + let ty = ty.node; + let ty: TypeWrapper = ty.into(); + ret = Some(ty.into()); + } + } + + let ret = ret.expect("expected return type"); let name = match node.node.declarator.node.kind.node { lang_c::ast::DeclaratorKind::Identifier(node) => node.node.name, @@ -70,6 +92,10 @@ impl CodeGeneration { let mut func = Function::new(name, fn_ty); + if extrn { + func.extrn(); + } + func.addBlock("entry"); let mut vars = HashMap::new(); @@ -91,39 +117,43 @@ impl CodeGeneration { let Statement::Compound(body) = node.node.statement.node else { unreachable!() }; - for stmt in body { - let stmt = stmt.node; + self.gen_compount(&mut func, &mut vars, body); + + self.module.add_raw(func); + } - match stmt { - BlockItem::Statement(node) => self.gen_stmt(&mut func, &mut vars, node.node), - BlockItem::Declaration(_node) => todo!("declerations"), + fn gen_compount(&mut self, func: &mut Function, vars: &mut HashMap, comp: Vec>) { + for block in comp { + let block = block.node; + + match block { + BlockItem::Statement(node) => self.gen_stmt(func, vars, node.node), + BlockItem::Declaration(node) => self.gen_decl(func, vars, node.node), BlockItem::StaticAssert(_) => todo!("static asserts"), } } - - self.module.add_raw(func); } fn gen_stmt(&mut self, func: &mut Function, vars: &mut HashMap, stmt: Statement) { match stmt { - Statement::Labeled(node) => todo!(), - Statement::Compound(vec) => todo!(), + Statement::Labeled(_node) => todo!(), + Statement::Compound(comp) => self.gen_compount(func, vars, comp), Statement::Expression(node) => { if let Some(expr) = node { let expr = expr.node; self.gen_stmt_expression(func, vars, expr) } else { panic!("empty expressions are currently not supported") } }, - Statement::If(node) => todo!(), + Statement::If(node) => self.gen_if(func, vars, node.node), Statement::Switch(node) => todo!(), Statement::While(node) => todo!(), Statement::DoWhile(node) => todo!(), Statement::For(node) => todo!(), - Statement::Goto(node) => todo!(), + Statement::Goto(_node) => todo!(), Statement::Continue => todo!(), Statement::Break => todo!(), Statement::Return(node) => self.gen_return(func, vars, node), - Statement::Asm(node) => todo!(), + Statement::Asm(_node) => todo!(), } } @@ -247,6 +277,75 @@ impl CodeGeneration { BinaryOperator::AssignBitwiseOr => todo!(), } } + + fn gen_decl(&mut self, func: &mut Function, vars: &mut HashMap, decl: Declaration) { + let mut var_ty = None; + + for specifier in decl.specifiers { + if let DeclarationSpecifier::TypeSpecifier(ty) = &specifier.node { + let ty = ty.node.to_owned(); + let ty: TypeWrapper = ty.into(); + + var_ty = Some(ty.into()); + } + } + + let var_ty: TypeMetadata = var_ty.expect("expected type"); + + for decl in decl.declarators { + let decl = decl.node; + + let name = match decl.declarator.node.kind.node { + DeclaratorKind::Identifier(node) => node.node.name, + DeclaratorKind::Abstract => todo!(), + DeclaratorKind::Declarator(_) => todo!(), + }; + + let ptr = func.BuildAlloca(var_ty); + + if let Some(init) = decl.initializer { + let init = init.node; + + if let Initializer::Expression(expr) = init { + let expr = expr.node; + + let tmp= self.gen_expression(func, vars, expr); + + func.BuildStore(ptr.clone(), tmp); + } else { todo!("list initializer") } + }; + + vars.insert(name, (ptr, var_ty)); + } + } + + fn gen_if(&mut self, func: &mut Function, vars: &mut HashMap, if_stmt: IfStatement) { + let cond = self.gen_expression(func, vars, if_stmt.condition.node); + + let curr = func.currentBlock(); + let then_block = func.addBlock(&format!("if{}.then", self.if_count)); + let else_block = func.addBlock(&format!("if{}.else", self.if_count)); + let after_block = func.addBlock(&format!("if{}.after", self.if_count)); + + func.setCurrBlock(curr); + self.if_count += 1; + + func.BuildBrCond(cond, &then_block, &else_block); + + func.setCurrBlock(then_block); + self.gen_stmt(func, vars, if_stmt.then_statement.node); + func.BuildBr(&after_block); + + func.setCurrBlock(else_block); + + if let Some(else_stmt) = if_stmt.else_statement { + self.gen_stmt(func, vars, else_stmt.node); + } + + func.BuildBr(&after_block); + + func.setCurrBlock(after_block); + } } struct TypeWrapper(pub TypeMetadata); diff --git a/tools/ycc/src/main.rs b/tools/ycc/src/main.rs index d8d3ae3a..adee30c3 100644 --- a/tools/ycc/src/main.rs +++ b/tools/ycc/src/main.rs @@ -1,12 +1,12 @@ -use std::process::exit; +use std::{io::Write, process::exit}; -use ygen::{Support::Cli, Target::Triple}; +use ygen::{Support::Cli, Target::{initializeAllTargets, Triple}}; use lang_c::driver::*; mod codegen; mod utils; -fn main() { +fn main() -> Result<(), Box>{ let mut cli = Cli::new("ycc", "Ygens c compiler", "(latest)", "Cr0a3"); // Standart stuff @@ -46,6 +46,12 @@ fn main() { } else if cli.opt("vv") { // verbose version information println!("ycc v(latest) (c) Cr0a3"); println!("Host-Target: {}", Triple::host()); + std::process::exit(0); + } + + if cli.opt("S") && cli.opt("emit-ir") { + println!("Error: ir and assembly can't be emitted at the same time"); + std::process::exit(-1); } let triple = { @@ -63,7 +69,7 @@ fn main() { }; let infile = cli.arg_val("in").unwrap(); - let out = utils::out_file(&infile, cli.arg_val("out")); + let mut out = utils::out_file(&infile, cli.arg_val("out"), cli.opt("S"), cli.opt("emit-ir")); let config = Config::default(); let parsed = parse(&config, infile); @@ -76,11 +82,25 @@ fn main() { let parsed = parsed.unwrap(); - let mut codegen = codegen::CodeGeneration::new(parsed.unit.0, triple); + let mut codegen = codegen::CodeGeneration::new(parsed.unit.0); codegen.codegen(); - let ir = codegen.module.dump(); + let mut targets = initializeAllTargets(triple)?; + + if cli.opt("emit-ir") { + let ir = codegen.module.dump(); + + out.write_all(&ir.into_bytes())?; + } else if cli.opt("S") { + let asm = codegen.module.emitAsm(triple, &mut targets)?; + + out.write_all(&asm.into_bytes())?; + } else { + let (obj, _) = codegen.module.emitMachineCode(triple, &mut targets, false)?; + + obj.emit(out, None)?; + } - println!("{}", ir); + Ok(()) } diff --git a/tools/ycc/src/utils.rs b/tools/ycc/src/utils.rs index 4e2aa53c..027cd611 100644 --- a/tools/ycc/src/utils.rs +++ b/tools/ycc/src/utils.rs @@ -1,28 +1,7 @@ use std::fs::File; -use std::io::Read; use std::process::exit; -pub fn read_in_file(path: &String) -> String { - let mut infile = match File::open(&path) { - Ok(file) => file, - Err(err) => { - println!("Error: {} {}", path, err); - exit(-1); - }, - }; - - let mut input = String::new(); - match infile.read_to_string(&mut input) { - Ok(_) => {}, - Err(err) => { - println!("Error: {} {}", path, err); - exit(-1); - } - }; - - input -} -pub fn out_file(in_path: &String, out_path: Option) -> File { +pub fn out_file(in_path: &String, out_path: Option, asm: bool, ir: bool) -> File { let path; if let Some(out_path) = out_path { path = out_path } @@ -40,7 +19,13 @@ pub fn out_file(in_path: &String, out_path: Option) -> File { name.push_str(slice); } - path = format!("{}.o", name); + if !asm && !ir { + path = format!("{}.o", name); + } else if asm { + path = format!("{}.asm", name); + } else { + path = format!("{}.ll", name); + } } match File::options().create(true).write(true).truncate(true).open(&path) {