diff --git a/src/irgen/mod.rs b/src/irgen/mod.rs index 1fe2de6..564591e 100644 --- a/src/irgen/mod.rs +++ b/src/irgen/mod.rs @@ -38,10 +38,8 @@ use core::cmp::Ordering; use core::convert::TryFrom; use core::{fmt, mem}; use std::collections::{BTreeMap, HashMap}; -use std::fmt::Binary; use std::ops::Deref; -use ir::BlockExit; use itertools::izip; use lang_c::ast::*; use lang_c::driver::Parse; @@ -992,29 +990,6 @@ impl IrgenFunc<'_> { })?; self.translate_initializer(ptr, &item.node.initializer.node, context)?; } - - // for (field, item) in fields.iter().zip(items) { - // if !item.node.designation.is_empty() { - // todo!("desiginator initializer list"); - // } - // if let Some(field_name) = field.name() { - // let (field_offset, field_dtype) = ptr_inner_dtype - // .get_offset_struct_field(field.name().unwrap(), self.structs) - // .unwrap(); - // let ptr = - // context.insert_instruction(ir::Instruction::GetElementPtr { - // ptr: ptr.clone(), - // offset: ir::Operand::constant(ir::Constant::int( - // field_offset.try_into().unwrap(), - // ir::Dtype::int(32), - // )), - // dtype: ir::Dtype::pointer(field_dtype), - // })?; - // self.translate_initializer(ptr, &item.node.initializer.node, context)?; - // } else { - - // } - // } } else { unreachable!(); } @@ -1274,48 +1249,38 @@ impl IrgenFunc<'_> { context: &mut Context, ) -> Result { match op { - BinaryOperator::Assign => { - let lhs = self.translate_expr_lvalue(lhs, context)?; - let rhs = self.translate_expr_rvalue(rhs, context)?; - let rhs = self.translate_typecast( - rhs, - lhs.dtype().get_pointer_inner().unwrap().clone(), - context, - )?; - let _unused = context.insert_instruction(ir::Instruction::Store { - ptr: lhs, - value: rhs.clone(), - })?; - Ok(rhs) + BinaryOperator::Assign => self.translate_assign(lhs, rhs, None, context), + BinaryOperator::AssignMultiply => { + self.translate_assign(lhs, rhs, Some(BinaryOperator::Multiply), context) + } + BinaryOperator::AssignDivide => { + self.translate_assign(lhs, rhs, Some(BinaryOperator::Divide), context) + } + BinaryOperator::AssignModulo => { + self.translate_assign(lhs, rhs, Some(BinaryOperator::Modulo), context) } BinaryOperator::AssignPlus => { - let rhs = self.translate_binary_op(&BinaryOperator::Plus, lhs, rhs, context)?; - let lhs = self.translate_expr_lvalue(lhs, context)?; - let rhs = self.translate_typecast( - rhs, - lhs.dtype().get_pointer_inner().unwrap().clone(), - context, - )?; - let _unused = context.insert_instruction(ir::Instruction::Store { - ptr: lhs, - value: rhs.clone(), - })?; - Ok(rhs) + self.translate_assign(lhs, rhs, Some(BinaryOperator::Plus), context) } BinaryOperator::AssignMinus => { - let rhs = self.translate_binary_op(&BinaryOperator::Minus, lhs, rhs, context)?; - let lhs = self.translate_expr_lvalue(lhs, context)?; - let rhs = self.translate_typecast( - rhs, - lhs.dtype().get_pointer_inner().unwrap().clone(), - context, - )?; - let _unused = context.insert_instruction(ir::Instruction::Store { - ptr: lhs, - value: rhs.clone(), - })?; - Ok(rhs) + self.translate_assign(lhs, rhs, Some(BinaryOperator::Minus), context) } + BinaryOperator::AssignShiftLeft => { + self.translate_assign(lhs, rhs, Some(BinaryOperator::ShiftLeft), context) + } + BinaryOperator::AssignShiftRight => { + self.translate_assign(lhs, rhs, Some(BinaryOperator::ShiftRight), context) + } + BinaryOperator::AssignBitwiseAnd => { + self.translate_assign(lhs, rhs, Some(BinaryOperator::BitwiseAnd), context) + } + BinaryOperator::AssignBitwiseXor => { + self.translate_assign(lhs, rhs, Some(BinaryOperator::BitwiseXor), context) + } + BinaryOperator::AssignBitwiseOr => { + self.translate_assign(lhs, rhs, Some(BinaryOperator::BitwiseOr), context) + } + BinaryOperator::LogicalAnd => { let lhs_dtype = self.dtypeof_expr(lhs); let rhs_dtype = self.dtypeof_expr(rhs); @@ -1333,76 +1298,15 @@ impl IrgenFunc<'_> { let lhs = self.translate_expr_rvalue(lhs, context)?; let lhs = self.translate_typecast(lhs, operand_dtype.clone(), context)?; - let condition1 = context.insert_instruction(ir::Instruction::BinOp { - op: BinaryOperator::NotEquals, - lhs, - rhs: ir::Operand::constant(ir::Constant::int(0, operand_dtype.clone())), - dtype: ir::Dtype::BOOL, - })?; - self.insert_block( - mem::replace(context, Context::new(end_bid)), - ir::BlockExit::ConditionalJump { - condition: condition1, - arg_then: ir::JumpArg::new(then_bid, Vec::new()), - arg_else: ir::JumpArg::new(else_bid, Vec::new()), - }, - ); - - let mut then_context = Context::new(then_bid); - let _unused = then_context.insert_instruction(ir::Instruction::Store { - ptr: tmp.clone(), - value: ir::Operand::constant(ir::Constant::int(1, ir::Dtype::BOOL)), - })?; - self.insert_block( - then_context, - ir::BlockExit::Jump { - arg: ir::JumpArg::new(end_bid, Vec::new()), - }, - ); - - let mut else_context = Context::new(else_bid); - let rhs = self.translate_expr_rvalue(rhs, &mut else_context)?; - let rhs = self.translate_typecast(rhs, operand_dtype.clone(), &mut else_context)?; - let condition2 = else_context.insert_instruction(ir::Instruction::BinOp { - op: BinaryOperator::NotEquals, - lhs: rhs, - rhs: ir::Operand::constant(ir::Constant::int(1, operand_dtype.clone())), - dtype: ir::Dtype::BOOL, - })?; - let _unused = else_context.insert_instruction(ir::Instruction::Store { - ptr: tmp.clone(), - value: condition2, + let zero = ir::Operand::constant(match operand_dtype { + ir::Dtype::Int { .. } => ir::Constant::int(0, operand_dtype.clone()), + ir::Dtype::Float { .. } => ir::Constant::float(0.0, operand_dtype.clone()), + _ => todo!(""), }); - self.insert_block( - else_context, - ir::BlockExit::Jump { - arg: ir::JumpArg::new(end_bid, Vec::new()), - }, - ); - - context.insert_instruction(ir::Instruction::Load { ptr: tmp }) - } - BinaryOperator::LogicalOr => { - let lhs_dtype = self.dtypeof_expr(lhs); - let rhs_dtype = self.dtypeof_expr(rhs); - let operand_dtype = self.merge_dtype( - self.integer_promotion(lhs_dtype), - self.integer_promotion(rhs_dtype), - ); - - let tmp = self.alloc_tempid(); - let tmp = self.translate_alloc(tmp, &ir::Dtype::BOOL, context)?; - - let then_bid = self.alloc_bid(); - let else_bid = self.alloc_bid(); - let end_bid = self.alloc_bid(); - - let lhs = self.translate_expr_rvalue(lhs, context)?; - let lhs = self.translate_typecast(lhs, operand_dtype.clone(), context)?; let condition1 = context.insert_instruction(ir::Instruction::BinOp { op: BinaryOperator::Equals, lhs, - rhs: ir::Operand::constant(ir::Constant::int(0, operand_dtype.clone())), + rhs: zero.clone(), dtype: ir::Dtype::BOOL, })?; self.insert_block( @@ -1432,7 +1336,83 @@ impl IrgenFunc<'_> { let condition2 = else_context.insert_instruction(ir::Instruction::BinOp { op: BinaryOperator::NotEquals, lhs: rhs, - rhs: ir::Operand::constant(ir::Constant::int(0, operand_dtype.clone())), + rhs: zero.clone(), + dtype: ir::Dtype::BOOL, + })?; + let _unused = else_context.insert_instruction(ir::Instruction::Store { + ptr: tmp.clone(), + value: condition2, + }); + self.insert_block( + else_context, + ir::BlockExit::Jump { + arg: ir::JumpArg::new(end_bid, Vec::new()), + }, + ); + + context.insert_instruction(ir::Instruction::Load { ptr: tmp }) + } + BinaryOperator::LogicalOr => { + // println!( + // "hi~ lhs: {} rhs: {}", + // lhs.write_string(), + // rhs.write_string() + // ); + let lhs_dtype = self.dtypeof_expr(lhs); + let rhs_dtype = self.dtypeof_expr(rhs); + let operand_dtype = self.merge_dtype( + self.integer_promotion(lhs_dtype), + self.integer_promotion(rhs_dtype), + ); + + let tmp = self.alloc_tempid(); + let tmp = self.translate_alloc(tmp, &ir::Dtype::BOOL, context)?; + + let then_bid = self.alloc_bid(); + let else_bid = self.alloc_bid(); + let end_bid = self.alloc_bid(); + + let lhs = self.translate_expr_rvalue(lhs, context)?; + let lhs = self.translate_typecast(lhs, operand_dtype.clone(), context)?; + let zero = ir::Operand::constant(match operand_dtype { + ir::Dtype::Int { .. } => ir::Constant::int(0, operand_dtype.clone()), + ir::Dtype::Float { .. } => ir::Constant::float(0.0, operand_dtype.clone()), + _ => todo!(""), + }); + let condition1 = context.insert_instruction(ir::Instruction::BinOp { + op: BinaryOperator::NotEquals, + lhs, + rhs: zero.clone(), + dtype: ir::Dtype::BOOL, + })?; + self.insert_block( + mem::replace(context, Context::new(end_bid)), + ir::BlockExit::ConditionalJump { + condition: condition1, + arg_then: ir::JumpArg::new(then_bid, Vec::new()), + arg_else: ir::JumpArg::new(else_bid, Vec::new()), + }, + ); + + let mut then_context = Context::new(then_bid); + let _unused = then_context.insert_instruction(ir::Instruction::Store { + ptr: tmp.clone(), + value: ir::Operand::constant(ir::Constant::int(1, ir::Dtype::BOOL)), + })?; + self.insert_block( + then_context, + ir::BlockExit::Jump { + arg: ir::JumpArg::new(end_bid, Vec::new()), + }, + ); + + let mut else_context = Context::new(else_bid); + let rhs = self.translate_expr_rvalue(rhs, &mut else_context)?; + let rhs = self.translate_typecast(rhs, operand_dtype.clone(), &mut else_context)?; + let condition2 = else_context.insert_instruction(ir::Instruction::BinOp { + op: BinaryOperator::NotEquals, + lhs: rhs, + rhs: zero.clone(), dtype: ir::Dtype::BOOL, })?; let _unused = else_context.insert_instruction(ir::Instruction::Store { @@ -1488,6 +1468,31 @@ impl IrgenFunc<'_> { } } + fn translate_assign( + &mut self, + lhs: &Expression, + rhs: &Expression, + op: Option, + context: &mut Context, + ) -> Result { + let rhs = (if let Some(op) = op { + self.translate_binary_op(&op, lhs, rhs, context) + } else { + self.translate_expr_rvalue(rhs, context) + })?; + let lhs = self.translate_expr_lvalue(lhs, context)?; + let rhs = self.translate_typecast( + rhs, + lhs.dtype().get_pointer_inner().unwrap().clone(), + context, + )?; + let _unused = context.insert_instruction(ir::Instruction::Store { + ptr: lhs.clone(), + value: rhs.clone(), + })?; + Ok(rhs) + } + fn translate_unary_op( &mut self, op: &UnaryOperator, @@ -1583,6 +1588,9 @@ impl IrgenFunc<'_> { } UnaryOperator::Complement => { let lhs = self.translate_expr_rvalue(operand, context)?; + let lhs_dtype = lhs.dtype(); + let lhs = + self.translate_typecast(lhs, self.integer_promotion(lhs_dtype), context)?; let dtype = lhs.dtype(); context.insert_instruction(ir::Instruction::BinOp { op: BinaryOperator::BitwiseXor, @@ -1591,8 +1599,14 @@ impl IrgenFunc<'_> { dtype: dtype.clone(), }) } - UnaryOperator::Plus | UnaryOperator::Minus | UnaryOperator::Negate => { + UnaryOperator::Plus | UnaryOperator::Minus => { let operand = self.translate_expr_rvalue(operand, context)?; + let operand_dtype = operand.dtype(); + let operand = self.translate_typecast( + operand, + self.integer_promotion(operand_dtype), + context, + )?; let dtype = operand.dtype(); context.insert_instruction(ir::Instruction::UnaryOp { op: op.clone(), @@ -1600,6 +1614,27 @@ impl IrgenFunc<'_> { dtype, }) } + UnaryOperator::Negate => { + let lhs = self.translate_expr_rvalue(operand, context)?; + let lhs_dtype = lhs.dtype(); + let lhs = self.translate_typecast( + lhs, + self.integer_promotion(lhs_dtype.clone()), + context, + )?; + let lhs_dtype = lhs.dtype(); + let rhs = ir::Operand::constant(match &lhs_dtype { + ir::Dtype::Int { .. } => ir::Constant::int(0, lhs_dtype.clone()), + ir::Dtype::Float { .. } => ir::Constant::float(0.0, lhs_dtype.clone()), + _ => todo!(), + }); + context.insert_instruction(ir::Instruction::BinOp { + op: BinaryOperator::Equals, + lhs, + rhs, + dtype: ir::Dtype::BOOL, + }) + } _ => todo!("unary op"), } } @@ -2084,6 +2119,7 @@ impl IrgenFunc<'_> { context: &mut Context, ) -> Result<(), IrgenErrorMessage> { for (i, (dtype, var)) in izip!(&signature.params, name_of_params).enumerate() { + // println!("dtype: {}", dtype); let ptr = self.translate_alloc(var.clone(), dtype, context)?; let _unused = context.insert_instruction(ir::Instruction::Store { ptr, @@ -2129,72 +2165,105 @@ impl IrgenFunc<'_> { value: ir::Operand, context: &mut Context, ) -> Result { - self.translate_typecast(value, ir::Dtype::BOOL, context) // TODO: Right? + let value_dtype = value.dtype(); + if value_dtype == ir::Dtype::BOOL { + return Ok(value); + } + let rhs = ir::Operand::constant(match &value_dtype { + ir::Dtype::Int { .. } => ir::Constant::int(0, value_dtype.clone()), + ir::Dtype::Float { .. } => ir::Constant::float(0.0, value_dtype.clone()), + _ => todo!(), + }); + context.insert_instruction(ir::Instruction::BinOp { + op: BinaryOperator::NotEquals, + lhs: value, + rhs, + dtype: ir::Dtype::BOOL, + }) } fn dtypeof_expr(&self, expr: &Expression) -> ir::Dtype { match expr { - Expression::Identifier(id) => self.lookup_symbol_table(&id.node.name).unwrap().dtype(), + Expression::Identifier(id) => self + .lookup_symbol_table(&id.node.name) + .unwrap() + .dtype() + .get_pointer_inner() + .unwrap() + .clone(), Expression::Constant(_) => ir::Constant::try_from(expr).unwrap().dtype(), + Expression::Call(call) => self + .dtypeof_expr(&call.node.callee.node) + .get_function_inner() + .unwrap() + .0 + .clone(), + Expression::SizeOfTy(_) | Expression::SizeOfVal(_) | Expression::AlignOf(_) => { + ir::Dtype::LONGLONG.set_signed(false) + } Expression::UnaryOperator(unary) => { let unary = &unary.node; match unary.operator.node { - UnaryOperator::PreDecrement - | UnaryOperator::PreIncrement + UnaryOperator::PostIncrement | UnaryOperator::PostDecrement - | UnaryOperator::PostIncrement => self.dtypeof_expr(&unary.operand.node), - UnaryOperator::Negate => ir::Dtype::int(32), - _ => todo!("unary dtypeof_expr"), + | UnaryOperator::PreIncrement + | UnaryOperator::PreDecrement + | UnaryOperator::Plus + | UnaryOperator::Minus + | UnaryOperator::Complement => self.dtypeof_expr(&unary.operand.node), + UnaryOperator::Negate => ir::Dtype::INT, + _ => { + println!("{}", unary.write_string()); + todo!("unary dtypeof_expr") + } } } Expression::BinaryOperator(binary) => { let binary = &binary.node; match binary.operator.node { - BinaryOperator::BitwiseAnd - | BinaryOperator::BitwiseOr - | BinaryOperator::BitwiseXor => self.integer_promotion(self.merge_dtype( - self.dtypeof_expr(&binary.lhs.node), - self.dtypeof_expr(&binary.rhs.node), - )), - BinaryOperator::LogicalAnd - | BinaryOperator::LogicalOr - | BinaryOperator::Equals - | BinaryOperator::NotEquals - | BinaryOperator::Less - | BinaryOperator::LessOrEqual - | BinaryOperator::Greater - | BinaryOperator::GreaterOrEqual => ir::Dtype::BOOL, - BinaryOperator::Assign => self - .dtypeof_expr(&binary.lhs.node) - .get_pointer_inner() - .cloned() - .unwrap(), - BinaryOperator::Plus + BinaryOperator::Multiply + | BinaryOperator::Divide + | BinaryOperator::Modulo + | BinaryOperator::Plus | BinaryOperator::Minus - | BinaryOperator::Multiply - | BinaryOperator::Divide => self.merge_dtype( + | BinaryOperator::ShiftLeft + | BinaryOperator::ShiftRight + | BinaryOperator::BitwiseAnd + | BinaryOperator::BitwiseXor + | BinaryOperator::BitwiseOr => self.merge_dtype( self.integer_promotion(self.dtypeof_expr(&binary.lhs.node)), self.integer_promotion(self.dtypeof_expr(&binary.rhs.node)), ), - _ => todo!("binary dtypeof_expr"), + BinaryOperator::Less + | BinaryOperator::Greater + | BinaryOperator::LessOrEqual + | BinaryOperator::GreaterOrEqual + | BinaryOperator::Equals + | BinaryOperator::NotEquals + | BinaryOperator::LogicalAnd + | BinaryOperator::LogicalOr => ir::Dtype::BOOL, + BinaryOperator::Assign + | BinaryOperator::AssignMultiply + | BinaryOperator::AssignDivide + | BinaryOperator::AssignModulo + | BinaryOperator::AssignPlus + | BinaryOperator::AssignMinus + | BinaryOperator::AssignShiftLeft + | BinaryOperator::AssignShiftRight + | BinaryOperator::AssignBitwiseAnd + | BinaryOperator::AssignBitwiseXor + | BinaryOperator::AssignBitwiseOr => self.dtypeof_expr(&binary.lhs.node), + _ => { + println!("{}", binary.write_string()); + todo!("binary dtypeof_expr") + } } } - Expression::SizeOfTy(_) | Expression::SizeOfVal(_) | Expression::AlignOf(_) => { - ir::Dtype::int(64).set_signed(false) - } Expression::Conditional(cond) => self.merge_dtype( self.dtypeof_expr(&cond.node.then_expression.node), self.dtypeof_expr(&cond.node.else_expression.node), ), - Expression::Call(call) => { - let callee_dtype = self.dtypeof_expr(&call.node.callee.node); - let (ret_dtype, _) = callee_dtype - .get_pointer_inner() - .unwrap() - .get_function_inner() - .unwrap(); - ret_dtype.clone() - } + Expression::Comma(comma) => self.dtypeof_expr(&comma.last().unwrap().node), _ => { println!("{}", expr.write_string()); todo!("dtypeof_expr")