grade-irgen-small.sh 스크립트 통과
This commit is contained in:
static
2025-04-07 02:23:35 +00:00
parent b1de106aeb
commit 2dafbaba70

View File

@@ -681,7 +681,7 @@ impl IrgenFunc<'_> {
let end_bid = self.alloc_bid(); let end_bid = self.alloc_bid();
let (cases, default_bid) = let (cases, default_bid) =
self.translate_switch_body(&stmt.statement.node, end_bid)?; self.translate_switch_body(&stmt.statement.node, end_bid, bid_continue)?;
self.insert_block( self.insert_block(
mem::replace(context, Context::new(end_bid)), mem::replace(context, Context::new(end_bid)),
@@ -879,7 +879,7 @@ impl IrgenFunc<'_> {
.map_err(|e| IrgenError::new(expr.write_string(), e))?, .map_err(|e| IrgenError::new(expr.write_string(), e))?,
None => ir::Operand::constant(ir::Constant::unit()), None => ir::Operand::constant(ir::Constant::unit()),
}; };
let value = self let value: ir::Operand = self
.translate_typecast(value, self.return_type.clone(), context) .translate_typecast(value, self.return_type.clone(), context)
.map_err(|e| IrgenError::new(expr.write_string(), e))?; .map_err(|e| IrgenError::new(expr.write_string(), e))?;
let end_bid = self.alloc_bid(); let end_bid = self.alloc_bid();
@@ -986,10 +986,61 @@ impl IrgenFunc<'_> {
context, context,
), ),
Expression::Conditional(cond) => self.translate_conditional(&cond.node, context), Expression::Conditional(cond) => self.translate_conditional(&cond.node, context),
Expression::SizeOfVal(sizeof) => {
let dtype = self.dtypeof_expr(&sizeof.node.0.node);
let (size, _) = dtype
.size_align_of(self.structs)
.map_err(|e| IrgenErrorMessage::InvalidDtype { dtype_error: e })?;
Ok(ir::Operand::constant(ir::Constant::int(
size.try_into().unwrap(),
ir::Dtype::LONGLONG.clone().set_signed(false),
)))
}
Expression::SizeOfTy(sizeof) => {
let dtype = ir::Dtype::try_from(&sizeof.node.0.node)
.map_err(|e| IrgenErrorMessage::InvalidDtype { dtype_error: e })?;
let dtype = dtype
.resolve_typedefs(self.typedefs)
.map_err(|e| IrgenErrorMessage::InvalidDtype { dtype_error: e })?;
let (size, _) = dtype
.size_align_of(self.structs)
.map_err(|e| IrgenErrorMessage::InvalidDtype { dtype_error: e })?;
Ok(ir::Operand::constant(ir::Constant::int(
size.try_into().unwrap(),
ir::Dtype::LONGLONG.clone().set_signed(false),
)))
}
Expression::AlignOf(alignof) => {
let dtype = ir::Dtype::try_from(&alignof.node.0.node)
.map_err(|e| IrgenErrorMessage::InvalidDtype { dtype_error: e })?;
let dtype = dtype
.resolve_typedefs(self.typedefs)
.map_err(|e| IrgenErrorMessage::InvalidDtype { dtype_error: e })?;
let (_, align) = dtype
.size_align_of(self.structs)
.map_err(|e| IrgenErrorMessage::InvalidDtype { dtype_error: e })?;
Ok(ir::Operand::constant(ir::Constant::int(
align.try_into().unwrap(),
ir::Dtype::LONGLONG.clone().set_signed(false),
)))
}
Expression::Comma(exprs) => self.translate_comma(exprs.deref(), context),
_ => todo!("c"), _ => todo!("c"),
} }
} }
fn translate_comma(
&mut self,
exprs: &[Node<Expression>],
context: &mut Context,
) -> Result<ir::Operand, IrgenErrorMessage> {
let operands = exprs
.iter()
.map(|e| self.translate_expr_rvalue(&e.node, context))
.collect::<Result<Vec<_>, _>>()?;
Ok(operands.last().unwrap().clone())
}
fn translate_conditional( fn translate_conditional(
&mut self, &mut self,
cond: &ConditionalExpression, cond: &ConditionalExpression,
@@ -1089,13 +1140,34 @@ impl IrgenFunc<'_> {
} }
} }
_ => { _ => {
// println!("merge failed: {} {}", lhs_dtype, rhs_dtype); println!("merge failed: {} {}", lhs_dtype, rhs_dtype);
todo!("merge") todo!("merge")
} }
} }
} }
} }
fn integer_promotion(&self, dtype: ir::Dtype) -> ir::Dtype {
match &dtype {
ir::Dtype::Int {
width,
is_signed,
is_const,
} => {
if *width < 32 {
ir::Dtype::Int {
width: 32,
is_signed: true,
is_const: *is_const,
}
} else {
dtype
}
}
_ => dtype,
}
}
fn translate_binary_op( fn translate_binary_op(
&mut self, &mut self,
op: &BinaryOperator, op: &BinaryOperator,
@@ -1107,6 +1179,11 @@ impl IrgenFunc<'_> {
BinaryOperator::Assign => { BinaryOperator::Assign => {
let lhs = self.translate_expr_lvalue(lhs, context)?; let lhs = self.translate_expr_lvalue(lhs, context)?;
let rhs = self.translate_expr_rvalue(rhs, 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 { let _unused = context.insert_instruction(ir::Instruction::Store {
ptr: lhs, ptr: lhs,
value: rhs.clone(), value: rhs.clone(),
@@ -1131,10 +1208,145 @@ impl IrgenFunc<'_> {
})?; })?;
Ok(rhs) Ok(rhs)
} }
BinaryOperator::LogicalAnd => {
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, None, 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::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,
});
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, None, 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())),
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(0, 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(0, operand_dtype.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 })
}
_ => { _ => {
let lhs = self.translate_expr_rvalue(lhs, context)?; let lhs = self.translate_expr_rvalue(lhs, context)?;
let rhs = self.translate_expr_rvalue(rhs, context)?; let rhs = self.translate_expr_rvalue(rhs, context)?;
let operand_dtype = self.merge_dtype(lhs.dtype(), rhs.dtype()); let operand_dtype = self.merge_dtype(
self.integer_promotion(lhs.dtype()),
self.integer_promotion(rhs.dtype()),
);
let result_dtype = match op { let result_dtype = match op {
BinaryOperator::Less BinaryOperator::Less
| BinaryOperator::Greater | BinaryOperator::Greater
@@ -1179,6 +1391,63 @@ impl IrgenFunc<'_> {
})?; })?;
Ok(rhs) Ok(rhs)
} }
UnaryOperator::PreDecrement => {
let lhs = self.translate_expr_rvalue(operand, context)?;
let dtype = lhs.dtype();
let rhs = context.insert_instruction(ir::Instruction::BinOp {
op: BinaryOperator::Minus,
lhs,
rhs: ir::Operand::constant(ir::Constant::int(1, dtype.clone())),
dtype: dtype.clone(),
})?;
let lhs = self.translate_expr_lvalue(operand, context)?;
let _unused = context.insert_instruction(ir::Instruction::Store {
ptr: lhs,
value: rhs.clone(),
})?;
Ok(rhs)
}
UnaryOperator::PostIncrement => {
let lhs = self.translate_expr_rvalue(operand, context)?;
let dtype = lhs.dtype();
let rhs = context.insert_instruction(ir::Instruction::BinOp {
op: BinaryOperator::Plus,
lhs: lhs.clone(),
rhs: ir::Operand::constant(ir::Constant::int(1, dtype.clone())),
dtype: dtype.clone(),
})?;
let lhs_lvalue = self.translate_expr_lvalue(operand, context)?;
let _unused = context.insert_instruction(ir::Instruction::Store {
ptr: lhs_lvalue,
value: rhs.clone(),
})?;
Ok(lhs)
}
UnaryOperator::PostDecrement => {
let lhs = self.translate_expr_rvalue(operand, context)?;
let dtype = lhs.dtype();
let rhs = context.insert_instruction(ir::Instruction::BinOp {
op: BinaryOperator::Minus,
lhs: lhs.clone(),
rhs: ir::Operand::constant(ir::Constant::int(1, dtype.clone())),
dtype: dtype.clone(),
})?;
let lhs_lvalue = self.translate_expr_lvalue(operand, context)?;
let _unused = context.insert_instruction(ir::Instruction::Store {
ptr: lhs_lvalue,
value: rhs.clone(),
})?;
Ok(lhs)
}
UnaryOperator::Address => {
let t = self.translate_expr_lvalue(operand, context)?;
// println!("{}", t.dtype());
Ok(t)
}
UnaryOperator::Indirection => {
let operand = self.translate_expr_rvalue(operand, context)?;
context.insert_instruction(ir::Instruction::Load { ptr: operand })
}
UnaryOperator::Complement => { UnaryOperator::Complement => {
let lhs = self.translate_expr_rvalue(operand, context)?; let lhs = self.translate_expr_rvalue(operand, context)?;
let dtype = lhs.dtype(); let dtype = lhs.dtype();
@@ -1246,6 +1515,7 @@ impl IrgenFunc<'_> {
&mut self, &mut self,
stmt: &Statement, stmt: &Statement,
end_bid: ir::BlockId, end_bid: ir::BlockId,
bid_continue: Option<ir::BlockId>,
) -> Result<(Vec<(ir::Constant, ir::JumpArg)>, ir::BlockId), IrgenError> { ) -> Result<(Vec<(ir::Constant, ir::JumpArg)>, ir::BlockId), IrgenError> {
let mut cases = Vec::new(); let mut cases = Vec::new();
let mut default = None; let mut default = None;
@@ -1266,6 +1536,7 @@ impl IrgenFunc<'_> {
&mut cases, &mut cases,
&mut default, &mut default,
end_bid, end_bid,
bid_continue,
)?; )?;
} }
_ => panic!("is unsupported"), _ => panic!("is unsupported"),
@@ -1285,6 +1556,7 @@ impl IrgenFunc<'_> {
cases: &mut Vec<(ir::Constant, ir::JumpArg)>, cases: &mut Vec<(ir::Constant, ir::JumpArg)>,
default: &mut Option<ir::BlockId>, default: &mut Option<ir::BlockId>,
end_bid: ir::BlockId, end_bid: ir::BlockId,
bid_continue: Option<ir::BlockId>,
) -> Result<(), IrgenError> { ) -> Result<(), IrgenError> {
let stmt = if let Statement::Labeled(stmt) = stmt { let stmt = if let Statement::Labeled(stmt) = stmt {
&stmt.node &stmt.node
@@ -1295,7 +1567,7 @@ impl IrgenFunc<'_> {
}; };
let bid = self.alloc_bid(); let bid = self.alloc_bid();
let case = self.translate_switch_body_label_statement(stmt, bid, end_bid)?; let case = self.translate_switch_body_label_statement(stmt, bid, end_bid, bid_continue)?;
if let Some(case) = case { if let Some(case) = case {
if !case.is_integer_constant() { if !case.is_integer_constant() {
return Err(IrgenError::new( return Err(IrgenError::new(
@@ -1335,6 +1607,7 @@ impl IrgenFunc<'_> {
stmt: &LabeledStatement, stmt: &LabeledStatement,
bid: ir::BlockId, bid: ir::BlockId,
end_bid: ir::BlockId, end_bid: ir::BlockId,
bid_continue: Option<ir::BlockId>,
) -> Result<Option<ir::Constant>, IrgenError> { ) -> Result<Option<ir::Constant>, IrgenError> {
let case = match &stmt.label.node { let case = match &stmt.label.node {
Label::Identifier(_) => panic!("`Label::Identifier` is unsupported"), Label::Identifier(_) => panic!("`Label::Identifier` is unsupported"),
@@ -1369,7 +1642,7 @@ impl IrgenFunc<'_> {
.translate_decl(&decl.node, &mut context) .translate_decl(&decl.node, &mut context)
.map_err(|e| IrgenError::new(decl.write_string(), e))?, .map_err(|e| IrgenError::new(decl.write_string(), e))?,
BlockItem::Statement(stmt) => { BlockItem::Statement(stmt) => {
self.translate_stmt(&stmt.node, &mut context, None, None)?; self.translate_stmt(&stmt.node, &mut context, bid_continue, None)?;
} }
_ => panic!("is unsupported"), _ => panic!("is unsupported"),
} }
@@ -1620,7 +1893,8 @@ impl IrgenFunc<'_> {
dtype: ir::Dtype, dtype: ir::Dtype,
context: &mut Context, context: &mut Context,
) -> Result<ir::Operand, IrgenErrorMessage> { ) -> Result<ir::Operand, IrgenErrorMessage> {
if value.dtype() == dtype { let value_dtype = value.dtype();
if value_dtype.clone().set_const(false) == dtype.clone().set_const(false) {
return Ok(value); return Ok(value);
} }
context.insert_instruction(ir::Instruction::TypeCast { context.insert_instruction(ir::Instruction::TypeCast {
@@ -1636,6 +1910,69 @@ impl IrgenFunc<'_> {
) -> Result<ir::Operand, IrgenErrorMessage> { ) -> Result<ir::Operand, IrgenErrorMessage> {
self.translate_typecast(value, ir::Dtype::BOOL, context) // TODO: Right? self.translate_typecast(value, ir::Dtype::BOOL, context) // TODO: Right?
} }
fn dtypeof_expr(&self, expr: &Expression) -> ir::Dtype {
match expr {
Expression::Identifier(id) => self.lookup_symbol_table(&id.node.name).unwrap().dtype(),
Expression::Constant(_) => ir::Constant::try_from(expr).unwrap().dtype(),
Expression::UnaryOperator(unary) => {
let unary = &unary.node;
match unary.operator.node {
UnaryOperator::PreDecrement
| UnaryOperator::PreIncrement
| UnaryOperator::PostDecrement
| UnaryOperator::PostIncrement => self.dtypeof_expr(&unary.operand.node),
UnaryOperator::Negate => ir::Dtype::int(32),
_ => 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(),
_ => 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()
}
_ => {
println!("{}", expr.write_string());
todo!("dtypeof_expr")
}
}
}
} }
#[inline] #[inline]