|
|
|
|
@ -27,8 +27,6 @@ pub struct MirgenContext<'s> {
|
|
|
|
|
pub(super) curr_func: Option<MirFunction>,
|
|
|
|
|
pub(super) curr_block: Option<MirBlock>,
|
|
|
|
|
pub func_map: HashMap<MirFunction, Function>,
|
|
|
|
|
pub release: HashSet<Value>,
|
|
|
|
|
pub curr_cond: Option<(Value, InstructionKind)>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub trait MirGen {
|
|
|
|
|
@ -44,17 +42,7 @@ impl MirGen for GlobalData {
|
|
|
|
|
mirgen.globals.insert(name.clone(), label.clone());
|
|
|
|
|
|
|
|
|
|
match global.value(mirgen.ctx) {
|
|
|
|
|
ConstantValue::Int32 { value, .. } => {
|
|
|
|
|
let new_label = MirLabel::from(label_name.clone());
|
|
|
|
|
mirgen.mctx.add_raw_data(new_label, RawData::Bytes(vec![*value], 4));
|
|
|
|
|
}
|
|
|
|
|
ConstantValue::Zero {typ} | ConstantValue::Undef { typ }=> {
|
|
|
|
|
let size = typ.bytewidth(mirgen.ctx);
|
|
|
|
|
mirgen.mctx.add_raw_data(label.clone(), RawData::Bss(size));
|
|
|
|
|
}
|
|
|
|
|
ConstantValue::GlobalPtr { name: global_name, .. } => {
|
|
|
|
|
mirgen.globals.insert(global_name.clone(), MirLabel::from(global_name));
|
|
|
|
|
}
|
|
|
|
|
_ => todo!(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -110,84 +98,15 @@ impl MirGen for ir::instruction::Instruction {
|
|
|
|
|
let lhs = self.get_operand(mirgen.ctx, 0).unwrap();
|
|
|
|
|
let rhs = self.get_operand(mirgen.ctx, 1).unwrap();
|
|
|
|
|
let temp_reg = mirgen.mctx.generate_vreg(regs::RegKind::Integer).into();
|
|
|
|
|
|
|
|
|
|
if !lhs.is_constant(mirgen.ctx) && !rhs.is_constant(mirgen.ctx) {
|
|
|
|
|
let lhs_reg = mirgen.generate_opd_reg(lhs);
|
|
|
|
|
let rhs_reg = mirgen.generate_opd_reg(rhs);
|
|
|
|
|
match op {
|
|
|
|
|
ir::instruction::BinaryOp::Add => {
|
|
|
|
|
let add = MirInst::add(&mut mirgen.mctx, temp_reg, lhs_reg, rhs_reg);
|
|
|
|
|
let _ = mirgen.curr_block.as_ref().unwrap().push_back(&mut mirgen.mctx, add);
|
|
|
|
|
}
|
|
|
|
|
_ => todo!("Unsupported binary operation: {:?}", op),
|
|
|
|
|
}
|
|
|
|
|
} else if !lhs.is_constant(mirgen.ctx) && rhs.is_constant(mirgen.ctx) {
|
|
|
|
|
let lhs_reg = mirgen.generate_opd_reg(lhs);
|
|
|
|
|
if let ir::value::ValueKind::Constant { value } = &rhs.deref(mirgen.ctx).unwrap().kind {
|
|
|
|
|
if let ConstantValue::Int32 { value, .. } = value {
|
|
|
|
|
match op {
|
|
|
|
|
ir::instruction::BinaryOp::Add => {
|
|
|
|
|
let addi = MirInst::addi(&mut mirgen.mctx, temp_reg, lhs_reg, *value as i32);
|
|
|
|
|
let _ = mirgen.curr_block.as_ref().unwrap().push_back(&mut mirgen.mctx, addi);
|
|
|
|
|
},
|
|
|
|
|
_ => todo!("Unsupported binary operation: {:?}", op),
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
panic!("Expected int32 onstant for right operand");
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
todo!();
|
|
|
|
|
}
|
|
|
|
|
} else if lhs.is_constant(mirgen.ctx) && rhs.is_constant(mirgen.ctx) {
|
|
|
|
|
if lhs.kind(mirgen.ctx).is_int32(mirgen.ctx){
|
|
|
|
|
let l_value;
|
|
|
|
|
let r_value;
|
|
|
|
|
let imm: i32;
|
|
|
|
|
if let ir::value::ValueKind::Constant { value } = &lhs.deref(mirgen.ctx).unwrap().kind {
|
|
|
|
|
if let ConstantValue::Int32 { value, .. } = value {
|
|
|
|
|
l_value = *value;
|
|
|
|
|
} else {
|
|
|
|
|
panic!("Expected int32 constant for left operand");
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
panic!("Expected int32 constant for left operand");
|
|
|
|
|
}
|
|
|
|
|
if let ir::value::ValueKind::Constant { value } = &rhs.deref(mirgen.ctx).unwrap().kind {
|
|
|
|
|
if let ConstantValue::Int32 { value, .. } = value {
|
|
|
|
|
r_value = *value;
|
|
|
|
|
} else {
|
|
|
|
|
panic!("Expected int32 constant for left operand");
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
panic!("Expected int32 constant for left operand");
|
|
|
|
|
}
|
|
|
|
|
match op {
|
|
|
|
|
ir::instruction::BinaryOp::Add => imm = l_value + r_value,
|
|
|
|
|
_ => todo!("Unsupported binary operation: {:?}", op),
|
|
|
|
|
}
|
|
|
|
|
mirgen.generate_movimm(temp_reg, imm);
|
|
|
|
|
} else {
|
|
|
|
|
panic!("Expected i32 constant for left operand");
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
let rhs_reg = mirgen.generate_opd_reg(rhs);
|
|
|
|
|
if let ir::value::ValueKind::Constant { value } = &lhs.deref(mirgen.ctx).unwrap().kind {
|
|
|
|
|
if let ConstantValue::Int32 { value, .. } = value {
|
|
|
|
|
match op {
|
|
|
|
|
ir::instruction::BinaryOp::Add => {
|
|
|
|
|
let addi = MirInst::addi(&mut mirgen.mctx, temp_reg, rhs_reg, *value);
|
|
|
|
|
let _ = mirgen.curr_block.as_ref().unwrap().push_back(&mut mirgen.mctx, addi);
|
|
|
|
|
}
|
|
|
|
|
_ => todo!("Unsupported binary operation: {:?}", op),
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
panic!("Unsupported constant type: {:?}", value);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
panic!("Expected int32 constant for left operand");
|
|
|
|
|
let lhs_reg = mirgen.generate_opd_reg(lhs);
|
|
|
|
|
let rhs_reg = mirgen.generate_opd_reg(rhs);
|
|
|
|
|
match op {
|
|
|
|
|
ir::instruction::BinaryOp::Add => {
|
|
|
|
|
let add = MirInst::add(&mut mirgen.mctx, temp_reg, lhs_reg, rhs_reg);
|
|
|
|
|
let _ = mirgen.curr_block.as_ref().unwrap().push_back(&mut mirgen.mctx, add);
|
|
|
|
|
}
|
|
|
|
|
_ => todo!("Unsupported binary operation: {:?}", op),
|
|
|
|
|
}
|
|
|
|
|
// 记录结果
|
|
|
|
|
mirgen.table.insert(result_val, MirOperand {
|
|
|
|
|
typ: result_val.kind(mirgen.ctx),
|
|
|
|
|
kind: MirOperandKind::Reg(temp_reg),
|
|
|
|
|
@ -198,10 +117,8 @@ impl MirGen for ir::instruction::Instruction {
|
|
|
|
|
MemAccessOp::Alloca { typ } => {
|
|
|
|
|
let mut size = typ.bitwidth(mirgen.ctx);
|
|
|
|
|
size = (size + 7) / 8;
|
|
|
|
|
let current_offset = mirgen.curr_func.unwrap().current_stack_size(&mirgen.mctx);
|
|
|
|
|
let mem_loc = MemLoc::RegOffset { base: regs::sp().into(), offset: mirgen.curr_func.unwrap().current_stack_size(&mirgen.mctx) };
|
|
|
|
|
let _ = mirgen.curr_func.unwrap().add_current_stack_size(&mut mirgen.mctx, size as i32);
|
|
|
|
|
let total_stack = 0;
|
|
|
|
|
let mem_loc = MemLoc::RegOffset { base: regs::sp().into(), offset: total_stack+current_offset };
|
|
|
|
|
let mopd = MirOperand {
|
|
|
|
|
typ,
|
|
|
|
|
kind: MirOperandKind::Mem(mem_loc),
|
|
|
|
|
@ -211,32 +128,9 @@ impl MirGen for ir::instruction::Instruction {
|
|
|
|
|
MemAccessOp::Store => {
|
|
|
|
|
let val = self.get_operand(mirgen.ctx, 0).unwrap();
|
|
|
|
|
let ptr = self.get_operand(mirgen.ctx, 1).unwrap();
|
|
|
|
|
let is_global_ptr =
|
|
|
|
|
if let ir::value::ValueKind::Constant { value} = &ptr.deref(mirgen.ctx).unwrap().kind {
|
|
|
|
|
matches!(value, ConstantValue::GlobalPtr { .. })
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
false
|
|
|
|
|
};
|
|
|
|
|
let mem_loc = if is_global_ptr {
|
|
|
|
|
let name =
|
|
|
|
|
if let ir::value::ValueKind::Constant {
|
|
|
|
|
value: ConstantValue::GlobalPtr { name, .. }
|
|
|
|
|
} = &ptr.deref(mirgen.ctx).unwrap().kind {name.clone()}
|
|
|
|
|
else {
|
|
|
|
|
unreachable!()
|
|
|
|
|
};
|
|
|
|
|
let label = mirgen.globals[&name].clone();
|
|
|
|
|
let temp_reg = mirgen.mctx.generate_vreg(regs::RegKind::Address).into();
|
|
|
|
|
mirgen.generate_adrp(temp_reg, label);
|
|
|
|
|
let mem = MemLoc::RegOffset { base: temp_reg, offset: 0 };
|
|
|
|
|
mem
|
|
|
|
|
}else {
|
|
|
|
|
let mem = match mirgen.table[&ptr].kind {
|
|
|
|
|
MirOperandKind::Mem(m) => m,
|
|
|
|
|
_ => unreachable!(),
|
|
|
|
|
};
|
|
|
|
|
mem
|
|
|
|
|
let mem_loc = match mirgen.table[&ptr].kind {
|
|
|
|
|
MirOperandKind::Mem(m) => m,
|
|
|
|
|
_ => unreachable!(),
|
|
|
|
|
};
|
|
|
|
|
match &val.deref(mirgen.ctx).unwrap().kind {
|
|
|
|
|
ir::value::ValueKind::Constant { value } => {
|
|
|
|
|
@ -260,36 +154,7 @@ impl MirGen for ir::instruction::Instruction {
|
|
|
|
|
MirOperandKind::Reg(reg) => {
|
|
|
|
|
mirgen.generate_str(reg, mem_loc);
|
|
|
|
|
}
|
|
|
|
|
MirOperandKind::Mem(MemLoc::Reg { address }) => {
|
|
|
|
|
mirgen.generate_str(address, mem_loc);
|
|
|
|
|
}
|
|
|
|
|
MirOperandKind::Mem(MemLoc::RegOffset { base, offset }) => {
|
|
|
|
|
let new_reg = mirgen.mctx.generate_vreg(regs::RegKind::Address).into();
|
|
|
|
|
let add = MirInst::addi(&mut mirgen.mctx, new_reg, base, offset);
|
|
|
|
|
mirgen.curr_block.as_ref().unwrap().push_back(&mut mirgen.mctx, add).unwrap();
|
|
|
|
|
let mem_loc = MemLoc::Reg { address: new_reg };
|
|
|
|
|
mirgen.generate_str(new_reg, mem_loc);
|
|
|
|
|
|
|
|
|
|
mirgen.table.insert(val, MirOperand {
|
|
|
|
|
typ: val.kind(mirgen.ctx),
|
|
|
|
|
kind: MirOperandKind::Mem(mem_loc),
|
|
|
|
|
});
|
|
|
|
|
mirgen.release.insert(val);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
MirOperandKind::Mem(MemLoc::Reg2Offset { base, offset }) => {
|
|
|
|
|
let new_reg = mirgen.mctx.generate_vreg(regs::RegKind::Address).into();
|
|
|
|
|
let add = MirInst::add(&mut mirgen.mctx, new_reg, base, offset);
|
|
|
|
|
mirgen.curr_block.as_ref().unwrap().push_back(&mut mirgen.mctx, add).unwrap();
|
|
|
|
|
mirgen.generate_str(new_reg, mem_loc);
|
|
|
|
|
|
|
|
|
|
let mem_loc = MemLoc::Reg { address: new_reg };
|
|
|
|
|
mirgen.table.insert(val, MirOperand {
|
|
|
|
|
typ: val.kind(mirgen.ctx),
|
|
|
|
|
kind: MirOperandKind::Mem(mem_loc),
|
|
|
|
|
});
|
|
|
|
|
mirgen.release.insert(val);
|
|
|
|
|
}
|
|
|
|
|
_ => todo!(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
_ => todo!()
|
|
|
|
|
@ -298,37 +163,11 @@ impl MirGen for ir::instruction::Instruction {
|
|
|
|
|
MemAccessOp::Load => {
|
|
|
|
|
let ptr_val = self.get_operand(mirgen.ctx, 0).unwrap();
|
|
|
|
|
let result_val = self.get_result(mirgen.ctx).unwrap();
|
|
|
|
|
// 检查是否是全局变量
|
|
|
|
|
let is_global_ptr =
|
|
|
|
|
if let ir::value::ValueKind::Constant { value} = &ptr_val.deref(mirgen.ctx).unwrap().kind {
|
|
|
|
|
matches!(value, ConstantValue::GlobalPtr { .. })
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
false
|
|
|
|
|
};
|
|
|
|
|
let mem_loc = if is_global_ptr {
|
|
|
|
|
let name =
|
|
|
|
|
if let ir::value::ValueKind::Constant {
|
|
|
|
|
value: ConstantValue::GlobalPtr { name, .. }
|
|
|
|
|
} = &ptr_val.deref(mirgen.ctx).unwrap().kind {name.clone()}
|
|
|
|
|
else {
|
|
|
|
|
unreachable!()
|
|
|
|
|
};
|
|
|
|
|
let label = mirgen.globals[&name].clone();
|
|
|
|
|
let temp_reg = mirgen.mctx.generate_vreg(regs::RegKind::Address).into();
|
|
|
|
|
|
|
|
|
|
mirgen.generate_adrp(temp_reg, label);
|
|
|
|
|
let mem = MemLoc::RegOffset { base: temp_reg, offset: 0 };
|
|
|
|
|
mem
|
|
|
|
|
} else {
|
|
|
|
|
let mem = match mirgen.table[&ptr_val].kind {
|
|
|
|
|
MirOperandKind::Mem(m) => m,
|
|
|
|
|
_ => unreachable!(),
|
|
|
|
|
};
|
|
|
|
|
mem
|
|
|
|
|
let mem_loc = match mirgen.table[&ptr_val].kind {
|
|
|
|
|
MirOperandKind::Mem(m) => m,
|
|
|
|
|
_ => unreachable!(),
|
|
|
|
|
};
|
|
|
|
|
let temp_reg = mirgen.mctx.generate_vreg(regs::RegKind::Integer).into()
|
|
|
|
|
;
|
|
|
|
|
let temp_reg = mirgen.mctx.generate_vreg(regs::RegKind::Integer).into();
|
|
|
|
|
mirgen.generate_ldr(temp_reg, mem_loc);
|
|
|
|
|
let mem_loc = MirOperandKind::Reg(temp_reg);
|
|
|
|
|
|
|
|
|
|
@ -371,8 +210,6 @@ impl<'s> MirgenContext<'s> {
|
|
|
|
|
curr_func: None,
|
|
|
|
|
curr_block: None,
|
|
|
|
|
func_map: HashMap::default(),
|
|
|
|
|
release: HashSet::default(),
|
|
|
|
|
curr_cond: None,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -413,22 +250,10 @@ impl<'s> MirgenContext<'s> {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for block in blocks {
|
|
|
|
|
self.curr_cond = None;
|
|
|
|
|
self.curr_block = Some(self.blocks[&block]);
|
|
|
|
|
for inst in block.iter(self.ctx) {
|
|
|
|
|
inst.mirgen(self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let mut temp_table = HashMap::default();
|
|
|
|
|
for (val, opd) in self.table.iter() {
|
|
|
|
|
if self.release.contains(val){
|
|
|
|
|
continue;
|
|
|
|
|
} else {
|
|
|
|
|
temp_table.insert(*val, *opd);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
self.release = HashSet::default();
|
|
|
|
|
self.table = temp_table;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
@ -457,10 +282,7 @@ impl<'s> MirgenContext<'s> {
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
MirOperandKind::Mem(mem_loc) => {
|
|
|
|
|
self.generate_ldr(regs::Reg::P(ret_reg), mem_loc);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
_ => todo!(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
_ => todo!(),
|
|
|
|
|
@ -469,7 +291,7 @@ impl<'s> MirgenContext<'s> {
|
|
|
|
|
|
|
|
|
|
pub fn generate_ret_reg(&mut self, ty: ir::typ::Typ) -> PReg {
|
|
|
|
|
if ty.is_ptr(self.ctx) {
|
|
|
|
|
regs::x0().into()
|
|
|
|
|
todo!()
|
|
|
|
|
} else {
|
|
|
|
|
regs::w0().into()
|
|
|
|
|
}
|
|
|
|
|
@ -490,14 +312,8 @@ impl<'s> MirgenContext<'s> {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn generate_movimm(&mut self, rn: Reg, imm: i32) {
|
|
|
|
|
let low = imm & 0xFFFF;
|
|
|
|
|
let high = (imm >> 16) & 0xFFFF;
|
|
|
|
|
let movz = MirInst::movz(&mut self.mctx, rn, low);
|
|
|
|
|
let movz = MirInst::movz(&mut self.mctx, rn, imm);
|
|
|
|
|
let _ = self.curr_block.as_ref().unwrap().push_back(&mut self.mctx, movz);
|
|
|
|
|
if high != 0 {
|
|
|
|
|
let movk = MirInst::movk(&mut self.mctx, rn, high);
|
|
|
|
|
let _ = self.curr_block.as_ref().unwrap().push_back(&mut self.mctx, movk);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn generate_str(&mut self, rm: Reg, mem_loc: MemLoc) {
|
|
|
|
|
@ -509,12 +325,5 @@ impl<'s> MirgenContext<'s> {
|
|
|
|
|
let ldr = MirInst::ldr(&mut self.mctx, rd, mem_loc);
|
|
|
|
|
let _ = self.curr_block.as_ref().unwrap().push_back(&mut self.mctx, ldr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn generate_adrp(&mut self, rd: Reg, label: MirLabel ) {
|
|
|
|
|
let adrp = MirInst::adrp(&mut self.mctx, rd, label.clone());
|
|
|
|
|
let _ = self.curr_block.as_ref().unwrap().push_back(&mut self.mctx, adrp);
|
|
|
|
|
let add_label = MirInst::add_label(&mut self.mctx, rd, rd, label.clone());
|
|
|
|
|
let _ = self.curr_block.as_ref().unwrap().push_back(&mut self.mctx, add_label);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|