refactor/cleanup of mir generation for arithmetic ops and preloading of constant lhs

This commit is contained in:
Janis 2024-08-26 15:58:51 +02:00
parent 06b1ec1763
commit eba0edb9e4

View file

@ -26,7 +26,37 @@ enum Type2 {
Pointer,
}
impl Into<mir::Type> for Type2 {
fn into(self) -> mir::Type {
self.mir_type()
}
}
impl Type2 {
fn mir_type(self) -> mir::Type {
match self {
Type2::Integral(_, bits) => mir::Type::from_bitsize_int(bits as u32),
Type2::Binary32 => mir::Type::SinglePrecision,
Type2::Binary64 => mir::Type::DoublePrecision,
Type2::Bool => mir::Type::from_bitsize_int(1),
Type2::Pointer => mir::Type::QWord,
}
}
fn is_signed(self) -> bool {
match self {
Type2::Integral(signed, _) => signed,
_ => false,
}
}
fn mir_unalignment(self) -> Option<(bool, u16)> {
match self {
Type2::Integral(signed, bits) => match bits {
8 | 16 | 32 | 64 => None,
bits => Some((signed, bits)),
},
_ => None,
}
}
fn size(&self) -> u32 {
match self {
Type2::Integral(_signed, bits) => bits.div_ceil(8) as u32,
@ -100,7 +130,7 @@ enum Inst {
/// ptr, index,
GetElementPtr(Type2),
/// size, align
Parameter,
Parameter(Type2),
/// lhs, rhs
Add(Type2),
/// lhs, rhs
@ -129,6 +159,16 @@ enum Inst {
Return,
}
impl Inst {
fn is_constant(self) -> bool {
match self {
Inst::ConstantU32 | Inst::ConstantU64 | Inst::ConstantMultiByte => true,
_ => false,
}
}
}
#[derive(Debug, Clone, Copy)]
struct Data {
lhs: u32,
@ -242,10 +282,11 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> {
for param in parameters {
variant!(Tag::Parameter { ty, .. } = self.tree.nodes.get_node(*param));
let ty = self.tree.type_of_node(*ty);
let ir = self.ir.push(
Inst::Parameter,
Some(Data::new(ty.size_of(), ty.align_of())),
);
let size = ty.size_of();
let align = ty.align_of();
let ir = self
.ir
.push(Inst::Parameter(ty.into()), Some(Data::new(size, align)));
self.lookup.insert(*param, NodeOrList::Node(ir));
}
@ -456,12 +497,12 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> {
let label = self.tree.strings.get_str(data.as_index());
writeln_indented!(indent - 1, w, "%{} = func {label}:", node)?;
}
Inst::Parameter => {
Inst::Parameter(ty) => {
let (size, align) = data.as_lhs_rhs();
writeln_indented!(
indent,
w,
"%{} = Param(size: {}, align: {})",
"%{} = param {ty} (size: {}, align: {})",
node,
size,
align
@ -1065,7 +1106,7 @@ impl<'a> Assembler<'a> {
}
registers.insert(dst_reg, node);
}
Inst::Parameter => {
Inst::Parameter(_) => {
let param_reg = Registers::sysv_param_idx(param_count).unwrap();
param_count += 1;
register_store.force_take(param_reg);
@ -1312,10 +1353,9 @@ impl<'a> MirBuilder<'a> {
let src = *mapping.get(&ptr).unwrap();
mir.gen_get_element_ptr(ty, src, idx)
}
Inst::Parameter => {
let (size, _) = data.unwrap().as_lhs_rhs();
let ty = mir::Type::from_bytesize_int(size);
mir.gen_param(ty)
Inst::Parameter(ty) => {
// let (size, _) = data.unwrap().as_lhs_rhs();
mir.gen_param(ty.into())
}
Inst::Add(ty) => {
let (src, dst) = data.unwrap().as_lhs_rhs();
@ -1349,188 +1389,156 @@ impl<'a> MirBuilder<'a> {
let lhs = *mapping.get(&src).unwrap();
let rhs = *mapping.get(&dst).unwrap();
match ty {
Type2::Integral(signed, bits) => match bits {
8 => mir.gen_sub(mir::Type::Byte, lhs, rhs),
16 => mir.gen_sub(mir::Type::Word, lhs, rhs),
32 => mir.gen_sub(mir::Type::DWord, lhs, rhs),
64 => mir.gen_sub(mir::Type::QWord, lhs, rhs),
64.. => {
unimplemented!()
}
bits => {
let ty = mir::Type::from_bitsize_int(bits as u32);
let unalignment = ty.mir_unalignment();
let ty = ty.mir_type();
let sum = mir.gen_sub(ty, lhs, rhs);
mir.gen_truncate(sum, ty, signed, bits)
}
},
Type2::Binary32 => mir.gen_sub(mir::Type::SinglePrecision, lhs, rhs),
Type2::Binary64 => mir.gen_sub(mir::Type::DoublePrecision, lhs, rhs),
Type2::Pointer => mir.gen_sub(mir::Type::QWord, lhs, rhs),
_ => unreachable!(),
let const_lhs = self.ir.ir.nodes[src as usize].is_constant();
let lhs = if const_lhs {
mir.gen_load_const(ty, src)
} else {
lhs
};
let sum = mir.gen_sub(ty, lhs, rhs);
if let Some((signed, bits)) = unalignment {
mir.gen_truncate(sum, ty, signed, bits)
} else {
sum
}
}
Inst::Mul(ty) => {
let (src, dst) = data.unwrap().as_lhs_rhs();
let lhs = *mapping.get(&src).unwrap();
let rhs = *mapping.get(&dst).unwrap();
let (lhs, rhs) = data.unwrap().as_lhs_rhs();
match ty {
Type2::Integral(signed, bits) => match bits {
8 => mir.gen_mul(mir::Type::Byte, signed, lhs, rhs),
16 => mir.gen_mul(mir::Type::Word, signed, lhs, rhs),
32 => mir.gen_mul(mir::Type::DWord, signed, lhs, rhs),
64 => mir.gen_mul(mir::Type::QWord, signed, lhs, rhs),
64.. => {
unimplemented!()
}
bits => {
let ty = mir::Type::from_bitsize_int(bits as u32);
let unalignment = ty.mir_unalignment();
let signed = ty.is_signed();
let ty = ty.mir_type();
let sum = mir.gen_mul(ty, signed, lhs, rhs);
mir.gen_truncate(sum, ty, signed, bits)
}
},
Type2::Binary32 => {
mir.gen_mul_unsigned(mir::Type::SinglePrecision, lhs, rhs)
}
Type2::Binary64 => {
mir.gen_mul_unsigned(mir::Type::DoublePrecision, lhs, rhs)
}
_ => unreachable!(),
let (lhs, rhs) = if self.ir.ir.nodes[lhs as usize].is_constant() {
(rhs, lhs)
} else {
(lhs, rhs)
};
let lhs = *mapping.get(&lhs).unwrap();
let rhs = *mapping.get(&rhs).unwrap();
let sum = mir.gen_mul(ty, signed, lhs, rhs);
if let Some((signed, bits)) = unalignment {
mir.gen_truncate(sum, ty, signed, bits)
} else {
sum
}
}
Inst::Div(ty) => {
let (src, dst) = data.unwrap().as_lhs_rhs();
let lhs = *mapping.get(&src).unwrap();
let rhs = *mapping.get(&dst).unwrap();
let (lhs, rhs) = data.unwrap().as_lhs_rhs();
match ty {
Type2::Integral(signed, bits) => match bits {
8 => mir.gen_div(mir::Type::Byte, signed, lhs, rhs),
16 => mir.gen_div(mir::Type::Word, signed, lhs, rhs),
32 => mir.gen_div(mir::Type::DWord, signed, lhs, rhs),
64 => mir.gen_div(mir::Type::QWord, signed, lhs, rhs),
64.. => {
unimplemented!()
}
bits => {
let ty = mir::Type::from_bitsize_int(bits as u32);
let unalignment = ty.mir_unalignment();
let signed = ty.is_signed();
let ty = ty.mir_type();
let sum = mir.gen_div(ty, signed, lhs, rhs);
mir.gen_truncate(sum, ty, signed, bits)
}
},
Type2::Binary32 => {
mir.gen_div_unsigned(mir::Type::SinglePrecision, lhs, rhs)
}
Type2::Binary64 => {
mir.gen_div_unsigned(mir::Type::DoublePrecision, lhs, rhs)
}
_ => unreachable!(),
let lhs = if self.ir.ir.nodes[lhs as usize].is_constant() {
mir.gen_load_const(ty, lhs)
} else {
lhs
};
let lhs = *mapping.get(&lhs).unwrap();
let rhs = *mapping.get(&rhs).unwrap();
let sum = mir.gen_div(ty, signed, lhs, rhs);
if let Some((signed, bits)) = unalignment {
mir.gen_truncate(sum, ty, signed, bits)
} else {
sum
}
}
Inst::Rem(ty) => {
let (src, dst) = data.unwrap().as_lhs_rhs();
let lhs = *mapping.get(&src).unwrap();
let rhs = *mapping.get(&dst).unwrap();
let (lhs, rhs) = data.unwrap().as_lhs_rhs();
match ty {
Type2::Integral(signed, bits) => match bits {
8 => mir.gen_rem(mir::Type::Byte, signed, lhs, rhs),
16 => mir.gen_rem(mir::Type::Word, signed, lhs, rhs),
32 => mir.gen_rem(mir::Type::DWord, signed, lhs, rhs),
64 => mir.gen_rem(mir::Type::QWord, signed, lhs, rhs),
64.. => {
unimplemented!()
}
bits => {
let ty = mir::Type::from_bitsize_int(bits as u32);
let unalignment = ty.mir_unalignment();
let signed = ty.is_signed();
let ty = ty.mir_type();
let sum = mir.gen_rem(ty, signed, lhs, rhs);
mir.gen_truncate(sum, ty, signed, bits)
}
},
Type2::Binary32 => {
mir.gen_rem_unsigned(mir::Type::SinglePrecision, lhs, rhs)
}
Type2::Binary64 => {
mir.gen_rem_unsigned(mir::Type::DoublePrecision, lhs, rhs)
}
_ => unreachable!(),
let lhs = if self.ir.ir.nodes[lhs as usize].is_constant() {
mir.gen_load_const(ty, lhs)
} else {
lhs
};
let lhs = *mapping.get(&lhs).unwrap();
let rhs = *mapping.get(&rhs).unwrap();
let sum = mir.gen_rem(ty, signed, lhs, rhs);
if let Some((signed, bits)) = unalignment {
mir.gen_truncate(sum, ty, signed, bits)
} else {
sum
}
}
Inst::BitAnd(ty) => {
let (src, dst) = data.unwrap().as_lhs_rhs();
let lhs = *mapping.get(&src).unwrap();
let rhs = *mapping.get(&dst).unwrap();
let (lhs, rhs) = data.unwrap().as_lhs_rhs();
match ty {
Type2::Integral(signed, bits) => match bits {
8 => mir.gen_bitand(mir::Type::Byte, lhs, rhs),
16 => mir.gen_bitand(mir::Type::Word, lhs, rhs),
32 => mir.gen_bitand(mir::Type::DWord, lhs, rhs),
64 => mir.gen_bitand(mir::Type::QWord, lhs, rhs),
64.. => {
unimplemented!()
}
bits => {
let ty = mir::Type::from_bitsize_int(bits as u32);
let unalignment = ty.mir_unalignment();
let ty = ty.mir_type();
let sum = mir.gen_bitand(ty, lhs, rhs);
mir.gen_truncate(sum, ty, signed, bits)
}
},
_ => unreachable!(),
let (lhs, rhs) = if self.ir.ir.nodes[lhs as usize].is_constant() {
(rhs, lhs)
} else {
(lhs, rhs)
};
let lhs = *mapping.get(&lhs).unwrap();
let rhs = *mapping.get(&rhs).unwrap();
let sum = mir.gen_bitand(ty, lhs, rhs);
if let Some((signed, bits)) = unalignment {
mir.gen_truncate(sum, ty, signed, bits)
} else {
sum
}
}
Inst::BitOr(ty) => {
let (src, dst) = data.unwrap().as_lhs_rhs();
let lhs = *mapping.get(&src).unwrap();
let rhs = *mapping.get(&dst).unwrap();
let (lhs, rhs) = data.unwrap().as_lhs_rhs();
match ty {
Type2::Integral(signed, bits) => match bits {
8 => mir.gen_bitor(mir::Type::Byte, lhs, rhs),
16 => mir.gen_bitor(mir::Type::Word, lhs, rhs),
32 => mir.gen_bitor(mir::Type::DWord, lhs, rhs),
64 => mir.gen_bitor(mir::Type::QWord, lhs, rhs),
64.. => {
unimplemented!()
}
bits => {
let ty = mir::Type::from_bitsize_int(bits as u32);
let unalignment = ty.mir_unalignment();
let ty = ty.mir_type();
let sum = mir.gen_bitor(ty, lhs, rhs);
mir.gen_truncate(sum, ty, signed, bits)
}
},
_ => unreachable!(),
let (lhs, rhs) = if self.ir.ir.nodes[lhs as usize].is_constant() {
(rhs, lhs)
} else {
(lhs, rhs)
};
let lhs = *mapping.get(&lhs).unwrap();
let rhs = *mapping.get(&rhs).unwrap();
let sum = mir.gen_bitor(ty, lhs, rhs);
if let Some((signed, bits)) = unalignment {
mir.gen_truncate(sum, ty, signed, bits)
} else {
sum
}
}
Inst::BitXOr(ty) => {
let (src, dst) = data.unwrap().as_lhs_rhs();
let lhs = *mapping.get(&src).unwrap();
let rhs = *mapping.get(&dst).unwrap();
let (lhs, rhs) = data.unwrap().as_lhs_rhs();
match ty {
Type2::Integral(signed, bits) => match bits {
8 => mir.gen_bitxor(mir::Type::Byte, lhs, rhs),
16 => mir.gen_bitxor(mir::Type::Word, lhs, rhs),
32 => mir.gen_bitxor(mir::Type::DWord, lhs, rhs),
64 => mir.gen_bitxor(mir::Type::QWord, lhs, rhs),
64.. => {
unimplemented!()
}
bits => {
let ty = mir::Type::from_bitsize_int(bits as u32);
let unalignment = ty.mir_unalignment();
let ty = ty.mir_type();
let sum = mir.gen_bitxor(ty, lhs, rhs);
mir.gen_truncate(sum, ty, signed, bits)
}
},
_ => unreachable!(),
let (lhs, rhs) = if self.ir.ir.nodes[lhs as usize].is_constant() {
(rhs, lhs)
} else {
(lhs, rhs)
};
let lhs = *mapping.get(&lhs).unwrap();
let rhs = *mapping.get(&rhs).unwrap();
let sum = mir.gen_bitxor(ty, lhs, rhs);
if let Some((signed, bits)) = unalignment {
mir.gen_truncate(sum, ty, signed, bits)
} else {
sum
}
}
Inst::ShiftLeft(ty) => {
@ -1591,26 +1599,24 @@ impl<'a> MirBuilder<'a> {
}
}
Inst::Negate(ty) => {
let src = data.unwrap().as_u32();
let src = *mapping.get(&src).unwrap();
let lhs = data.unwrap().as_u32();
match ty {
Type2::Integral(signed, bits) => match bits {
8 => mir.gen_negate(mir::Type::Byte, src),
16 => mir.gen_negate(mir::Type::Word, src),
32 => mir.gen_negate(mir::Type::DWord, src),
64 => mir.gen_negate(mir::Type::QWord, src),
64.. => {
unimplemented!()
}
bits => {
let ty = mir::Type::from_bitsize_int(bits as u32);
let unalignment = ty.mir_unalignment();
let ty = ty.mir_type();
let sum = mir.gen_negate(ty, src);
mir.gen_truncate(sum, ty, signed, bits)
}
},
_ => unreachable!(),
let lhs = if self.ir.ir.nodes[lhs as usize].is_constant() {
mir.gen_load_const(ty, lhs)
} else {
lhs
};
let lhs = *mapping.get(&lhs).unwrap();
let sum = mir.gen_negate(ty, lhs);
if let Some((signed, bits)) = unalignment {
mir.gen_truncate(sum, ty, signed, bits)
} else {
sum
}
}
Inst::ReturnValue => {