diff --git a/src/triples.rs b/src/triples.rs index 9c3f3fa..0ac0b0c 100644 --- a/src/triples.rs +++ b/src/triples.rs @@ -26,7 +26,37 @@ enum Type2 { Pointer, } +impl Into 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 => {