mirror of
https://github.com/kmc7468/cs420.git
synced 2025-12-15 15:08:52 +00:00
HW7 (2)
This commit is contained in:
@@ -11,6 +11,7 @@ use crate::{Translate, asm, ir};
|
|||||||
pub struct Asmgen {
|
pub struct Asmgen {
|
||||||
functions: Vec<asm::Section<asm::Function>>,
|
functions: Vec<asm::Section<asm::Function>>,
|
||||||
variables: Vec<asm::Section<asm::Variable>>,
|
variables: Vec<asm::Section<asm::Variable>>,
|
||||||
|
phinode_counter: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Asmgen {
|
impl Default for Asmgen {
|
||||||
@@ -18,6 +19,7 @@ impl Default for Asmgen {
|
|||||||
Asmgen {
|
Asmgen {
|
||||||
functions: Vec::new(),
|
functions: Vec::new(),
|
||||||
variables: Vec::new(),
|
variables: Vec::new(),
|
||||||
|
phinode_counter: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -46,18 +48,47 @@ struct Context {
|
|||||||
insts: Vec<asm::Instruction>,
|
insts: Vec<asm::Instruction>,
|
||||||
stack_offsets: HashMap<ir::RegisterId, u64>,
|
stack_offsets: HashMap<ir::RegisterId, u64>,
|
||||||
stack_allocation: u64,
|
stack_allocation: u64,
|
||||||
|
new_blocks: Vec<(asm::Label, Vec<asm::Instruction>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Asmgen {
|
impl Asmgen {
|
||||||
fn translate_decl(&mut self, name: &String, decl: &ir::Declaration) {
|
fn translate_decl(&mut self, name: &String, decl: &ir::Declaration) {
|
||||||
match decl {
|
match decl {
|
||||||
ir::Declaration::Variable { dtype, initializer } => todo!(),
|
ir::Declaration::Variable { dtype, initializer } => {
|
||||||
|
if let Some(initializer) = initializer {
|
||||||
|
let constant = get_constant_from_initializer(initializer);
|
||||||
|
let value = match constant {
|
||||||
|
ir::Constant::Int { value, width, .. } => {
|
||||||
|
if width == 8 {
|
||||||
|
asm::Directive::Byte(value as u8)
|
||||||
|
} else if width == 16 {
|
||||||
|
asm::Directive::Half(value as u16)
|
||||||
|
} else if width == 32 {
|
||||||
|
asm::Directive::Word(value as u32)
|
||||||
|
} else if width == 64 {
|
||||||
|
asm::Directive::Quad(value as u64)
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => todo!(),
|
||||||
|
};
|
||||||
|
self.variables.push(asm::Section::new(
|
||||||
|
vec![
|
||||||
|
asm::Directive::Globl(asm::Label(name.clone())),
|
||||||
|
asm::Directive::Section(asm::SectionType::Data),
|
||||||
|
asm::Directive::Type(asm::Label(name.clone()), asm::SymbolType::Object),
|
||||||
|
],
|
||||||
|
asm::Variable::new(asm::Label(name.clone()), vec![value]),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
ir::Declaration::Function {
|
ir::Declaration::Function {
|
||||||
signature,
|
signature,
|
||||||
definition,
|
definition,
|
||||||
} => {
|
} => {
|
||||||
if let Some(definition) = definition {
|
if let Some(definition) = definition {
|
||||||
let mut context = self.translate_prologue(definition);
|
let mut context = self.translate_prologue(signature, definition);
|
||||||
self.translate_block(
|
self.translate_block(
|
||||||
name,
|
name,
|
||||||
definition.bid_init,
|
definition.bid_init,
|
||||||
@@ -80,6 +111,10 @@ impl Asmgen {
|
|||||||
Some(asm::Label::new(name, *bid)),
|
Some(asm::Label::new(name, *bid)),
|
||||||
context.insts,
|
context.insts,
|
||||||
));
|
));
|
||||||
|
for (label, insts) in std::mem::replace(&mut context.new_blocks, Vec::new())
|
||||||
|
{
|
||||||
|
blocks.push(asm::Block::new(Some(label), insts));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.functions.push(asm::Section::new(
|
self.functions.push(asm::Section::new(
|
||||||
@@ -98,11 +133,19 @@ impl Asmgen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn translate_prologue(&mut self, definition: &ir::FunctionDefinition) -> Context {
|
fn translate_prologue(
|
||||||
|
&mut self,
|
||||||
|
signature: &ir::FunctionSignature,
|
||||||
|
definition: &ir::FunctionDefinition,
|
||||||
|
) -> Context {
|
||||||
let mut stack_allocation = 0;
|
let mut stack_allocation = 0;
|
||||||
let mut stack_offsets = HashMap::new();
|
let mut stack_offsets = HashMap::new();
|
||||||
|
|
||||||
for (bid, block) in &definition.blocks {
|
for (bid, block) in &definition.blocks {
|
||||||
|
for (aid, dtype) in block.phinodes.iter().enumerate() {
|
||||||
|
let _ = stack_offsets.insert(ir::RegisterId::arg(*bid, aid), stack_allocation);
|
||||||
|
stack_allocation += ceil_to_multiple_of_16(get_dtype_size(dtype));
|
||||||
|
}
|
||||||
for (iid, inst) in block.instructions.iter().enumerate() {
|
for (iid, inst) in block.instructions.iter().enumerate() {
|
||||||
let _ = stack_offsets.insert(ir::RegisterId::temp(*bid, iid), stack_allocation);
|
let _ = stack_offsets.insert(ir::RegisterId::temp(*bid, iid), stack_allocation);
|
||||||
stack_allocation += ceil_to_multiple_of_16(get_dtype_size(&inst.dtype()));
|
stack_allocation += ceil_to_multiple_of_16(get_dtype_size(&inst.dtype()));
|
||||||
@@ -116,7 +159,11 @@ impl Asmgen {
|
|||||||
|
|
||||||
stack_allocation += 16; // s0, ra
|
stack_allocation += 16; // s0, ra
|
||||||
|
|
||||||
let insts = vec![
|
for offset in stack_offsets.values_mut() {
|
||||||
|
*offset = stack_allocation - *offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut insts = vec![
|
||||||
asm::Instruction::IType {
|
asm::Instruction::IType {
|
||||||
instr: asm::IType::ADDI,
|
instr: asm::IType::ADDI,
|
||||||
rd: asm::Register::Sp,
|
rd: asm::Register::Sp,
|
||||||
@@ -142,10 +189,24 @@ impl Asmgen {
|
|||||||
imm: asm::Immediate::Value(!16 + 1),
|
imm: asm::Immediate::Value(!16 + 1),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// TODO: Floating point or optimizations
|
||||||
|
for (i, dtype) in signature.params.iter().enumerate() {
|
||||||
|
insts.push(asm::Instruction::SType {
|
||||||
|
instr: asm::SType::SD,
|
||||||
|
rs1: asm::Register::S0,
|
||||||
|
rs2: asm::Register::arg(asm::RegisterType::Integer, i),
|
||||||
|
imm: asm::Immediate::Value(
|
||||||
|
stack_offsets[&ir::RegisterId::arg(definition.bid_init, i)],
|
||||||
|
),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
Context {
|
Context {
|
||||||
insts,
|
insts,
|
||||||
stack_offsets,
|
stack_offsets,
|
||||||
stack_allocation,
|
stack_allocation,
|
||||||
|
new_blocks: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,7 +335,7 @@ impl Asmgen {
|
|||||||
self.translate_load_operand(value, rs2, context);
|
self.translate_load_operand(value, rs2, context);
|
||||||
context.insts.push(asm::Instruction::SType {
|
context.insts.push(asm::Instruction::SType {
|
||||||
instr: asm::SType::store(value_dtype),
|
instr: asm::SType::store(value_dtype),
|
||||||
rs1: asm::Register::Sp,
|
rs1: asm::Register::S0,
|
||||||
rs2,
|
rs2,
|
||||||
imm: asm::Immediate::Value(context.stack_offsets[ptr_rid]),
|
imm: asm::Immediate::Value(context.stack_offsets[ptr_rid]),
|
||||||
});
|
});
|
||||||
@@ -282,34 +343,87 @@ impl Asmgen {
|
|||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ir::Instruction::Load { ptr } => {
|
ir::Instruction::Load { ptr } => match ptr {
|
||||||
let (ptr_rid, ptr_dtype) = ptr.get_register().unwrap();
|
ir::Operand::Constant(ir::Constant::GlobalVariable { name, dtype }) => {
|
||||||
let value_dtype = ptr_dtype.get_pointer_inner().unwrap().clone();
|
let rd = get_lhs_register(&dtype);
|
||||||
let rd = get_lhs_register(&value_dtype);
|
context
|
||||||
match ptr_rid {
|
.insts
|
||||||
ir::RegisterId::Temp { .. } => {
|
.push(asm::Instruction::Pseudo(asm::Pseudo::La {
|
||||||
let rs1 = get_rhs_register(ptr_dtype);
|
rd: asm::Register::T0,
|
||||||
self.translate_load_operand(ptr, rs1, context);
|
symbol: asm::Label(name.clone()),
|
||||||
context.insts.push(asm::Instruction::IType {
|
}));
|
||||||
instr: asm::IType::load(value_dtype.clone()),
|
context.insts.push(asm::Instruction::IType {
|
||||||
rd,
|
instr: asm::IType::load(dtype.clone()),
|
||||||
rs1,
|
rd,
|
||||||
imm: asm::Immediate::Value(0),
|
rs1: asm::Register::T0,
|
||||||
});
|
imm: asm::Immediate::Value(0),
|
||||||
self.translate_store_result(&rid, value_dtype, rs1, context);
|
});
|
||||||
}
|
self.translate_store_result(&rid, dtype.clone(), rd, context);
|
||||||
ir::RegisterId::Local { aid } => {
|
|
||||||
let rs1 = get_lhs_register(ptr_dtype);
|
|
||||||
context.insts.push(asm::Instruction::IType {
|
|
||||||
instr: asm::IType::load(value_dtype.clone()),
|
|
||||||
rd,
|
|
||||||
rs1: asm::Register::Sp,
|
|
||||||
imm: asm::Immediate::Value(context.stack_offsets[ptr_rid]),
|
|
||||||
});
|
|
||||||
self.translate_store_result(&rid, value_dtype, rs1, context);
|
|
||||||
}
|
|
||||||
_ => todo!(),
|
|
||||||
}
|
}
|
||||||
|
ir::Operand::Register {
|
||||||
|
rid: ptr_rid,
|
||||||
|
dtype: ptr_dtype,
|
||||||
|
} => {
|
||||||
|
let value_dtype = ptr_dtype.get_pointer_inner().unwrap().clone();
|
||||||
|
let rd = get_lhs_register(&value_dtype);
|
||||||
|
match ptr_rid {
|
||||||
|
ir::RegisterId::Temp { .. } => {
|
||||||
|
let rs1 = get_rhs_register(ptr_dtype);
|
||||||
|
self.translate_load_operand(ptr, rs1, context);
|
||||||
|
context.insts.push(asm::Instruction::IType {
|
||||||
|
instr: asm::IType::load(value_dtype.clone()),
|
||||||
|
rd,
|
||||||
|
rs1,
|
||||||
|
imm: asm::Immediate::Value(0),
|
||||||
|
});
|
||||||
|
self.translate_store_result(&rid, value_dtype, rd, context);
|
||||||
|
}
|
||||||
|
ir::RegisterId::Local { aid } => {
|
||||||
|
let rs1 = get_lhs_register(ptr_dtype);
|
||||||
|
context.insts.push(asm::Instruction::IType {
|
||||||
|
instr: asm::IType::load(value_dtype.clone()),
|
||||||
|
rd,
|
||||||
|
rs1: asm::Register::S0,
|
||||||
|
imm: asm::Immediate::Value(context.stack_offsets[ptr_rid]),
|
||||||
|
});
|
||||||
|
self.translate_store_result(&rid, value_dtype, rd, context);
|
||||||
|
}
|
||||||
|
_ => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => todo!(),
|
||||||
|
},
|
||||||
|
ir::Instruction::Call {
|
||||||
|
callee,
|
||||||
|
args,
|
||||||
|
return_type,
|
||||||
|
} => {
|
||||||
|
for (i, arg) in args.iter().enumerate() {
|
||||||
|
// TODO: FloatingPoint
|
||||||
|
self.translate_load_operand(
|
||||||
|
arg,
|
||||||
|
asm::Register::arg(asm::RegisterType::Integer, i),
|
||||||
|
context,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
context
|
||||||
|
.insts
|
||||||
|
.push(asm::Instruction::Pseudo(asm::Pseudo::Call {
|
||||||
|
offset: asm::Label(
|
||||||
|
callee
|
||||||
|
.get_constant()
|
||||||
|
.unwrap()
|
||||||
|
.get_global_variable_name()
|
||||||
|
.unwrap(),
|
||||||
|
),
|
||||||
|
}));
|
||||||
|
// TODO
|
||||||
|
self.translate_store_result(
|
||||||
|
&rid,
|
||||||
|
return_type.clone(),
|
||||||
|
asm::Register::A0,
|
||||||
|
context,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
ir::Instruction::TypeCast {
|
ir::Instruction::TypeCast {
|
||||||
value,
|
value,
|
||||||
@@ -326,17 +440,33 @@ impl Asmgen {
|
|||||||
|
|
||||||
match &block.exit {
|
match &block.exit {
|
||||||
ir::BlockExit::Jump { arg } => {
|
ir::BlockExit::Jump { arg } => {
|
||||||
// TODO: Phinode
|
context
|
||||||
context.insts.push(asm::Instruction::Pseudo(asm::Pseudo::J {
|
.insts
|
||||||
offset: asm::Label::new(name, arg.bid),
|
.append(&mut self.translate_phinode(name, arg, context));
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
ir::BlockExit::ConditionalJump {
|
ir::BlockExit::ConditionalJump {
|
||||||
condition,
|
condition,
|
||||||
arg_then,
|
arg_then,
|
||||||
arg_else,
|
arg_else,
|
||||||
} => {
|
} => {
|
||||||
// TODO: Phinode
|
let arg_then_label = if arg_then.args.is_empty() {
|
||||||
|
asm::Label::new(name, arg_then.bid)
|
||||||
|
} else {
|
||||||
|
let phinode_insts = self.translate_phinode(name, arg_then, context);
|
||||||
|
let label = asm::Label(format!("{name}_P{}", self.phinode_counter));
|
||||||
|
self.phinode_counter += 1;
|
||||||
|
context.new_blocks.push((label.clone(), phinode_insts));
|
||||||
|
label
|
||||||
|
};
|
||||||
|
let arg_else_label = if arg_else.args.is_empty() {
|
||||||
|
asm::Label::new(name, arg_else.bid)
|
||||||
|
} else {
|
||||||
|
let phinode_insts = self.translate_phinode(name, arg_else, context);
|
||||||
|
let label = asm::Label(format!("{name}_P{}", self.phinode_counter));
|
||||||
|
self.phinode_counter += 1;
|
||||||
|
context.new_blocks.push((label.clone(), phinode_insts));
|
||||||
|
label
|
||||||
|
};
|
||||||
|
|
||||||
let rs1 = get_lhs_register(&condition.dtype());
|
let rs1 = get_lhs_register(&condition.dtype());
|
||||||
self.translate_load_operand(condition, rs1, context);
|
self.translate_load_operand(condition, rs1, context);
|
||||||
@@ -351,18 +481,26 @@ impl Asmgen {
|
|||||||
instr: asm::BType::Bne,
|
instr: asm::BType::Bne,
|
||||||
rs1,
|
rs1,
|
||||||
rs2: asm::Register::Zero,
|
rs2: asm::Register::Zero,
|
||||||
imm: asm::Label::new(name, arg_else.bid),
|
imm: arg_else_label,
|
||||||
});
|
});
|
||||||
context.insts.push(asm::Instruction::Pseudo(asm::Pseudo::J {
|
context.insts.push(asm::Instruction::Pseudo(asm::Pseudo::J {
|
||||||
offset: asm::Label::new(name, arg_then.bid),
|
offset: arg_then_label,
|
||||||
}));
|
})); // TODO: 최적화 가능?
|
||||||
}
|
}
|
||||||
ir::BlockExit::Switch {
|
ir::BlockExit::Switch {
|
||||||
value,
|
value,
|
||||||
default,
|
default,
|
||||||
cases,
|
cases,
|
||||||
} => {
|
} => {
|
||||||
// TODO: Phinode
|
let default_label = if default.args.is_empty() {
|
||||||
|
asm::Label::new(name, default.bid)
|
||||||
|
} else {
|
||||||
|
let phinode_insts = self.translate_phinode(name, default, context);
|
||||||
|
let label = asm::Label(format!("{name}_P{}", self.phinode_counter));
|
||||||
|
self.phinode_counter += 1;
|
||||||
|
context.new_blocks.push((label.clone(), phinode_insts));
|
||||||
|
label
|
||||||
|
};
|
||||||
|
|
||||||
let rs1 = get_lhs_register(&value.dtype());
|
let rs1 = get_lhs_register(&value.dtype());
|
||||||
let rs2 = get_rhs_register(&value.dtype());
|
let rs2 = get_rhs_register(&value.dtype());
|
||||||
@@ -370,17 +508,28 @@ impl Asmgen {
|
|||||||
|
|
||||||
for (case, arg) in cases {
|
for (case, arg) in cases {
|
||||||
self.translate_load_operand(&ir::Operand::constant(case.clone()), rs2, context);
|
self.translate_load_operand(&ir::Operand::constant(case.clone()), rs2, context);
|
||||||
|
|
||||||
|
let case_label = if arg.args.is_empty() {
|
||||||
|
asm::Label::new(name, arg.bid)
|
||||||
|
} else {
|
||||||
|
let phinode_insts = self.translate_phinode(name, arg, context);
|
||||||
|
let label = asm::Label(format!("{name}_P{}", self.phinode_counter));
|
||||||
|
self.phinode_counter += 1;
|
||||||
|
context.new_blocks.push((label.clone(), phinode_insts));
|
||||||
|
label
|
||||||
|
};
|
||||||
|
|
||||||
context.insts.push(asm::Instruction::BType {
|
context.insts.push(asm::Instruction::BType {
|
||||||
instr: asm::BType::Beq,
|
instr: asm::BType::Beq,
|
||||||
rs1,
|
rs1,
|
||||||
rs2,
|
rs2,
|
||||||
imm: asm::Label::new(name, arg.bid),
|
imm: case_label,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
context.insts.push(asm::Instruction::Pseudo(asm::Pseudo::J {
|
context.insts.push(asm::Instruction::Pseudo(asm::Pseudo::J {
|
||||||
offset: asm::Label::new(name, default.bid),
|
offset: default_label,
|
||||||
}));
|
})); // TODO: 최적화 가능?
|
||||||
}
|
}
|
||||||
ir::BlockExit::Return { value } => {
|
ir::BlockExit::Return { value } => {
|
||||||
// TODO
|
// TODO
|
||||||
@@ -399,6 +548,9 @@ impl Asmgen {
|
|||||||
) {
|
) {
|
||||||
match operand {
|
match operand {
|
||||||
ir::Operand::Constant(c) => match c {
|
ir::Operand::Constant(c) => match c {
|
||||||
|
ir::Constant::Undef { dtype } => context
|
||||||
|
.insts
|
||||||
|
.push(asm::Instruction::Pseudo(asm::Pseudo::Li { rd, imm: 0 })),
|
||||||
ir::Constant::Int {
|
ir::Constant::Int {
|
||||||
value,
|
value,
|
||||||
width,
|
width,
|
||||||
@@ -409,12 +561,15 @@ impl Asmgen {
|
|||||||
rd,
|
rd,
|
||||||
imm: *value as u64,
|
imm: *value as u64,
|
||||||
})),
|
})),
|
||||||
_ => todo!(),
|
_ => {
|
||||||
|
println!("{c}");
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
ir::Operand::Register { rid, dtype } => context.insts.push(asm::Instruction::IType {
|
ir::Operand::Register { rid, dtype } => context.insts.push(asm::Instruction::IType {
|
||||||
instr: asm::IType::load(dtype.clone()),
|
instr: asm::IType::load(dtype.clone()),
|
||||||
rd,
|
rd,
|
||||||
rs1: asm::Register::Sp,
|
rs1: asm::Register::S0,
|
||||||
imm: asm::Immediate::Value(context.stack_offsets[rid]),
|
imm: asm::Immediate::Value(context.stack_offsets[rid]),
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
@@ -429,11 +584,121 @@ impl Asmgen {
|
|||||||
) {
|
) {
|
||||||
context.insts.push(asm::Instruction::SType {
|
context.insts.push(asm::Instruction::SType {
|
||||||
instr: asm::SType::store(dtype),
|
instr: asm::SType::store(dtype),
|
||||||
rs1: asm::Register::Sp,
|
rs1: asm::Register::S0,
|
||||||
rs2: rs,
|
rs2: rs,
|
||||||
imm: asm::Immediate::Value(context.stack_offsets[rid]),
|
imm: asm::Immediate::Value(context.stack_offsets[rid]),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn translate_phinode(
|
||||||
|
&mut self,
|
||||||
|
name: &String,
|
||||||
|
arg: &ir::JumpArg,
|
||||||
|
context: &Context,
|
||||||
|
) -> Vec<asm::Instruction> {
|
||||||
|
let mut phinode_stack_offsets = HashMap::new();
|
||||||
|
let mut phinode_stack_allocations = 0;
|
||||||
|
|
||||||
|
for (aid, arg) in arg.args.iter().enumerate() {
|
||||||
|
let _ = phinode_stack_offsets.insert(aid, phinode_stack_allocations);
|
||||||
|
phinode_stack_allocations += ceil_to_multiple_of_16(get_dtype_size(&arg.dtype()));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut phinode_insts = Vec::new();
|
||||||
|
if phinode_stack_allocations > 0 {
|
||||||
|
phinode_insts.push(asm::Instruction::IType {
|
||||||
|
instr: asm::IType::ADDI,
|
||||||
|
rd: asm::Register::Sp,
|
||||||
|
rs1: asm::Register::Sp,
|
||||||
|
imm: asm::Immediate::Value(!phinode_stack_allocations + 1),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let bid = arg.bid;
|
||||||
|
for (aid, arg) in arg.args.iter().enumerate() {
|
||||||
|
let rs1 = get_lhs_register(&arg.dtype());
|
||||||
|
phinode_insts.push(asm::Instruction::IType {
|
||||||
|
instr: asm::IType::load(arg.dtype()),
|
||||||
|
rd: rs1,
|
||||||
|
rs1: asm::Register::S0,
|
||||||
|
imm: asm::Immediate::Value(context.stack_offsets[&ir::RegisterId::arg(bid, aid)]),
|
||||||
|
});
|
||||||
|
phinode_insts.push(asm::Instruction::SType {
|
||||||
|
instr: asm::SType::store(arg.dtype()),
|
||||||
|
rs1: asm::Register::Sp,
|
||||||
|
rs2: rs1,
|
||||||
|
imm: asm::Immediate::Value(phinode_stack_offsets[&aid]),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (aid, arg) in arg.args.iter().enumerate() {
|
||||||
|
let rs1 = get_lhs_register(&arg.dtype());
|
||||||
|
match arg {
|
||||||
|
ir::Operand::Constant(c) => match c {
|
||||||
|
ir::Constant::Int {
|
||||||
|
value,
|
||||||
|
width,
|
||||||
|
is_signed,
|
||||||
|
} => phinode_insts.push(asm::Instruction::Pseudo(asm::Pseudo::Li {
|
||||||
|
rd: rs1,
|
||||||
|
imm: *value as u64,
|
||||||
|
})),
|
||||||
|
_ => todo!(),
|
||||||
|
},
|
||||||
|
ir::Operand::Register { rid, .. } => {
|
||||||
|
if let ir::RegisterId::Arg {
|
||||||
|
bid: arg_bid,
|
||||||
|
aid: arg_aid,
|
||||||
|
} = rid
|
||||||
|
{
|
||||||
|
if *arg_bid == bid {
|
||||||
|
phinode_insts.push(asm::Instruction::IType {
|
||||||
|
instr: asm::IType::load(arg.dtype()),
|
||||||
|
rd: rs1,
|
||||||
|
rs1: asm::Register::Sp,
|
||||||
|
imm: asm::Immediate::Value(phinode_stack_offsets[arg_aid]),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
phinode_insts.push(asm::Instruction::IType {
|
||||||
|
instr: asm::IType::load(arg.dtype()),
|
||||||
|
rd: rs1,
|
||||||
|
rs1: asm::Register::S0,
|
||||||
|
imm: asm::Immediate::Value(context.stack_offsets[rid]),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
phinode_insts.push(asm::Instruction::IType {
|
||||||
|
instr: asm::IType::load(arg.dtype()),
|
||||||
|
rd: rs1,
|
||||||
|
rs1: asm::Register::S0,
|
||||||
|
imm: asm::Immediate::Value(context.stack_offsets[rid]),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
phinode_insts.push(asm::Instruction::SType {
|
||||||
|
instr: asm::SType::store(arg.dtype()),
|
||||||
|
rs1: asm::Register::S0,
|
||||||
|
rs2: rs1,
|
||||||
|
imm: asm::Immediate::Value(context.stack_offsets[&ir::RegisterId::arg(bid, aid)]),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if phinode_stack_allocations > 0 {
|
||||||
|
phinode_insts.push(asm::Instruction::IType {
|
||||||
|
instr: asm::IType::ADDI,
|
||||||
|
rd: asm::Register::Sp,
|
||||||
|
rs1: asm::Register::Sp,
|
||||||
|
imm: asm::Immediate::Value(phinode_stack_allocations),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
phinode_insts.push(asm::Instruction::Pseudo(asm::Pseudo::J {
|
||||||
|
offset: asm::Label::new(name, bid),
|
||||||
|
}));
|
||||||
|
|
||||||
|
phinode_insts
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_lhs_register(dtype: &ir::Dtype) -> asm::Register {
|
fn get_lhs_register(dtype: &ir::Dtype) -> asm::Register {
|
||||||
@@ -494,3 +759,13 @@ fn upgrade_dtype(dtype: &ir::Dtype) -> ir::Dtype {
|
|||||||
_ => dtype.clone(),
|
_ => dtype.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_constant_from_initializer(initializer: &ast::Initializer) -> ir::Constant {
|
||||||
|
match initializer {
|
||||||
|
ast::Initializer::Expression(expression) => match &expression.node {
|
||||||
|
ast::Expression::Constant(constant) => ir::Constant::try_from(&constant.node).unwrap(),
|
||||||
|
_ => panic!(),
|
||||||
|
},
|
||||||
|
_ => panic!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user