mirror of
https://github.com/kmc7468/cs420.git
synced 2025-12-15 15:08:52 +00:00
HW2 (2)
grade-irgen-small.sh 스크립트 통과
This commit is contained in:
351
src/irgen/mod.rs
351
src/irgen/mod.rs
@@ -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]
|
||||||
|
|||||||
Reference in New Issue
Block a user