From 52d2c2bfeed7742e8dc5ef3a06683cb5277ec644 Mon Sep 17 00:00:00 2001 From: static Date: Tue, 8 Apr 2025 06:08:29 +0000 Subject: [PATCH] HW2 (4) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit examples/c 디렉터리 아래에 있는 예제 모두 통과하는 상태 --- src/irgen/mod.rs | 217 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 190 insertions(+), 27 deletions(-) diff --git a/src/irgen/mod.rs b/src/irgen/mod.rs index c36b32d..1fe2de6 100644 --- a/src/irgen/mod.rs +++ b/src/irgen/mod.rs @@ -916,16 +916,14 @@ impl IrgenFunc<'_> { ir::Dtype::Int { .. } | ir::Dtype::Float { .. } | ir::Dtype::Pointer { .. } - | ir::Dtype::Array { .. } => { - let value = if let Some(initializer) = &init_decl.node.initializer { - Some(self.translate_initializer(&initializer.node, context)?) - } else { - None + | ir::Dtype::Array { .. } + | ir::Dtype::Struct { .. } => { + let ptr = self.translate_alloc(name, &dtype, context)?; + if let Some(initializer) = &init_decl.node.initializer { + self.translate_initializer(ptr, &initializer.node, context)?; }; - let _unused = self.translate_alloc(name, &dtype, value, context)?; } ir::Dtype::Function { .. } => todo!("g"), - ir::Dtype::Struct { .. } => todo!("h"), ir::Dtype::Typedef { .. } => unreachable!(), } } @@ -934,13 +932,95 @@ impl IrgenFunc<'_> { fn translate_initializer( &mut self, + ptr: ir::Operand, initializer: &Initializer, context: &mut Context, - ) -> Result { + ) -> Result<(), IrgenErrorMessage> { match initializer { - Initializer::Expression(expr) => self.translate_expr_rvalue(&expr.node, context), - Initializer::List(_) => panic!("Initializer::List is unsupported"), + Initializer::Expression(expr) => { + let value = self.translate_expr_rvalue(&expr.node, context)?; + let dtype = ptr.dtype().get_pointer_inner().cloned().unwrap(); + let value = self.translate_typecast(value, dtype, context)?; + let _unused = context.insert_instruction(ir::Instruction::Store { ptr, value })?; + } + Initializer::List(items) => { + let ptr_inner_dtype = ptr.dtype().get_pointer_inner().unwrap().clone(); + if let Some(inner) = ptr_inner_dtype.get_array_inner() { + let inner_ptr = ir::Dtype::pointer(inner.clone()); + let (inner_size, _) = inner + .size_align_of(self.structs) + .map_err(|e| IrgenErrorMessage::InvalidDtype { dtype_error: e })?; + for (i, item) in items.iter().enumerate() { + if !item.node.designation.is_empty() { + todo!("desiginator initializer list"); + } + let ptr = context.insert_instruction(ir::Instruction::GetElementPtr { + ptr: ptr.clone(), + offset: ir::Operand::constant(ir::Constant::int( + (inner_size * i).try_into().unwrap(), + ir::Dtype::int(32), + )), + dtype: inner_ptr.clone(), + })?; + self.translate_initializer(ptr, &item.node.initializer.node, context)?; + } + } else if let Some(name) = ptr_inner_dtype.get_struct_name() { + let struct_dtype = self + .structs + .get(name.as_ref().unwrap()) + .cloned() + .unwrap() + .unwrap(); + let fields = struct_dtype.get_struct_fields().unwrap().as_ref().unwrap(); + let (_, _, field_offsets) = struct_dtype + .get_struct_size_align_offsets() + .unwrap() + .as_ref() + .unwrap(); + for ((field, field_offset), item) in fields.iter().zip(field_offsets).zip(items) + { + if !item.node.designation.is_empty() { + todo!("desiginator initializer list"); + } + 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.deref().clone()), + })?; + 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!(); + } + } } + Ok(()) } fn translate_expr_rvalue( @@ -1025,6 +1105,24 @@ impl IrgenFunc<'_> { ))) } Expression::Comma(exprs) => self.translate_comma(exprs.deref(), context), + Expression::Member(member) => { + let member = &member.node; + let ptr = self.translate_member_op( + &member.operator.node, + &member.expression.node, + &member.identifier.node, + context, + )?; + if let Some(inner) = ptr.dtype().get_pointer_inner().unwrap().get_array_inner() { + context.insert_instruction(ir::Instruction::GetElementPtr { + ptr, + offset: ir::Operand::constant(ir::Constant::int(0, ir::Dtype::int(32))), + dtype: ir::Dtype::pointer(inner.clone()), + }) + } else { + context.insert_instruction(ir::Instruction::Load { ptr }) + } + } _ => todo!("c"), } } @@ -1071,7 +1169,7 @@ impl IrgenFunc<'_> { self.translate_typecast(else_val, merged_dtype.clone(), &mut else_context)?; let var = self.alloc_tempid(); - let ptr = self.translate_alloc(var, &merged_dtype.clone(), None, context)?; + let ptr = self.translate_alloc(var, &merged_dtype.clone(), context)?; let _unused = then_context.insert_instruction(ir::Instruction::Store { ptr: ptr.clone(), @@ -1193,6 +1291,11 @@ impl IrgenFunc<'_> { 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(), @@ -1202,6 +1305,11 @@ impl IrgenFunc<'_> { 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(), @@ -1217,7 +1325,7 @@ impl IrgenFunc<'_> { ); let tmp = self.alloc_tempid(); - let tmp = self.translate_alloc(tmp, &ir::Dtype::BOOL, None, context)?; + let tmp = self.translate_alloc(tmp, &ir::Dtype::BOOL, context)?; let then_bid = self.alloc_bid(); let else_bid = self.alloc_bid(); @@ -1283,7 +1391,7 @@ impl IrgenFunc<'_> { ); let tmp = self.alloc_tempid(); - let tmp = self.translate_alloc(tmp, &ir::Dtype::BOOL, None, context)?; + let tmp = self.translate_alloc(tmp, &ir::Dtype::BOOL, context)?; let then_bid = self.alloc_bid(); let else_bid = self.alloc_bid(); @@ -1765,7 +1873,62 @@ impl IrgenFunc<'_> { BinaryOperator::Index => self.translate_index_op(&binary.node.lhs.node, &binary.node.rhs.node, context), _ => Err(IrgenErrorMessage::Misc { message: "binary operator expression cannot be used as l-value except index operator expression".to_string() }), } - _ => todo!("expr lvalue") + Expression::Member(member) => { + let member = &member.node; + self.translate_member_op(&member.operator.node, &member.expression.node, &member.identifier.node, context) + } + Expression::Call(call) => { + let res = self.translate_func_call(&call.node, context)?; + let temp_id = self.alloc_tempid(); + let ptr = self.translate_alloc(temp_id, &res.dtype(), context)?; + let _unused = context.insert_instruction(ir::Instruction::Store { ptr: ptr.clone(), value: res })?; + Ok(ptr) + } + _ => { + println!("{}", expr.write_string()); + todo!("expr lvalue") + } + } + } + + fn translate_member_op( + &mut self, + op: &MemberOperator, + expr: &Expression, + id: &Identifier, + context: &mut Context, + ) -> Result { + match op { + MemberOperator::Direct => { + let expr = self.translate_expr_lvalue(expr, context)?; + let struct_dtype = expr.dtype().get_pointer_inner().unwrap().clone(); + let (field_offset, field_dtype) = struct_dtype + .get_offset_struct_field(&id.name, self.structs) + .expect("no field"); + context.insert_instruction(ir::Instruction::GetElementPtr { + ptr: expr, + offset: ir::Operand::constant(ir::Constant::int( + field_offset.try_into().unwrap(), + ir::Dtype::int(32), + )), + dtype: ir::Dtype::pointer(field_dtype), + }) + } + MemberOperator::Indirect => { + let expr = self.translate_expr_rvalue(expr, context)?; + let struct_dtype = expr.dtype().get_pointer_inner().unwrap().clone(); + let (field_offset, field_dtype) = struct_dtype + .get_offset_struct_field(&id.name, self.structs) + .expect("no field"); + context.insert_instruction(ir::Instruction::GetElementPtr { + ptr: expr, + offset: ir::Operand::constant(ir::Constant::int( + field_offset.try_into().unwrap(), + ir::Dtype::int(32), + )), + dtype: ir::Dtype::pointer(field_dtype), + }) + } } } @@ -1921,11 +2084,11 @@ impl IrgenFunc<'_> { context: &mut Context, ) -> Result<(), IrgenErrorMessage> { for (i, (dtype, var)) in izip!(&signature.params, name_of_params).enumerate() { - let value = Some(ir::Operand::register( - ir::RegisterId::arg(bid_init, i), - dtype.clone(), - )); - let _unused = self.translate_alloc(var.clone(), dtype, value, context)?; + let ptr = self.translate_alloc(var.clone(), dtype, context)?; + let _unused = context.insert_instruction(ir::Instruction::Store { + ptr, + value: ir::Operand::register(ir::RegisterId::arg(bid_init, i), dtype.clone()), + })?; self.phinodes_init .push(Named::new(Some(var.clone()), dtype.clone())); } @@ -1937,19 +2100,12 @@ impl IrgenFunc<'_> { &mut self, var: String, dtype: &ir::Dtype, - value: Option, context: &mut Context, ) -> Result { let rid = self.insert_alloc(Named::new(Some(var.clone()), dtype.clone())); let ptr = ir::Operand::register(rid, ir::Dtype::pointer(dtype.clone())); self.insert_symbol_table_entry(var, ptr.clone())?; - - if let Some(value) = value { - let value = self.translate_typecast(value, dtype.clone(), context)?; - context.insert_instruction(ir::Instruction::Store { ptr, value }) - } else { - Ok(ptr) - } + Ok(ptr) } fn translate_typecast( @@ -2013,6 +2169,13 @@ impl IrgenFunc<'_> { .get_pointer_inner() .cloned() .unwrap(), + BinaryOperator::Plus + | BinaryOperator::Minus + | BinaryOperator::Multiply + | BinaryOperator::Divide => 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"), } }