fix register not cleared before reading bool

This commit is contained in:
Folkert 2023-06-11 13:34:41 +02:00
parent cb5241380f
commit 2eaf158053
No known key found for this signature in database
GPG key ID: 1F17F6FFD112B97C
5 changed files with 93 additions and 51 deletions

View file

@ -965,33 +965,32 @@ impl Assembler<AArch64GeneralReg, AArch64FloatReg> for AArch64Assembler {
}
#[inline(always)]
fn movsx_reg64_base32(buf: &mut Vec<'_, u8>, dst: AArch64GeneralReg, offset: i32, size: u8) {
debug_assert!(size <= 8);
if size == 8 {
Self::mov_reg64_base32(buf, dst, offset);
} else if size == 4 {
todo!("sign extending 4 byte values");
} else if size == 2 {
todo!("sign extending 2 byte values");
} else if size == 1 {
todo!("sign extending 1 byte values");
} else {
internal_error!("Invalid size for sign extension: {}", size);
fn movsx_reg_base32(
buf: &mut Vec<'_, u8>,
register_width: RegisterWidth,
dst: AArch64GeneralReg,
offset: i32,
) {
match register_width {
RegisterWidth::W8 => todo!("sign extend 1 byte values"),
RegisterWidth::W16 => todo!("sign extend 2 byte values"),
RegisterWidth::W32 => todo!("sign extend 4 byte values"),
RegisterWidth::W64 => Self::mov_reg64_base32(buf, dst, offset),
}
}
#[inline(always)]
fn movzx_reg64_base32(buf: &mut Vec<'_, u8>, dst: AArch64GeneralReg, offset: i32, size: u8) {
debug_assert!(size <= 8);
if size == 8 {
Self::mov_reg64_base32(buf, dst, offset);
} else if size == 4 {
todo!("zero extending 4 byte values");
} else if size == 2 {
todo!("zero extending 2 byte values");
} else if size == 1 {
todo!("zero extending 1 byte values");
} else {
internal_error!("Invalid size for zero extension: {}", size);
fn movzx_reg_base32(
buf: &mut Vec<'_, u8>,
register_width: RegisterWidth,
dst: AArch64GeneralReg,
offset: i32,
) {
match register_width {
RegisterWidth::W8 => todo!("zero extend 1 byte values"),
RegisterWidth::W16 => todo!("zero extend 2 byte values"),
RegisterWidth::W32 => todo!("zero extend 4 byte values"),
RegisterWidth::W64 => Self::mov_reg64_base32(buf, dst, offset),
}
}

View file

@ -391,10 +391,19 @@ pub trait Assembler<GeneralReg: RegTrait, FloatReg: RegTrait>: Sized + Copy {
/// Sign extends the data at `offset` with `size` as it copies it to `dst`
/// size must be less than or equal to 8.
fn movsx_reg64_base32(buf: &mut Vec<'_, u8>, dst: GeneralReg, offset: i32, size: u8);
/// Zero extends the data at `offset` with `size` as it copies it to `dst`
/// size must be less than or equal to 8.
fn movzx_reg64_base32(buf: &mut Vec<'_, u8>, dst: GeneralReg, offset: i32, size: u8);
fn movsx_reg_base32(
buf: &mut Vec<'_, u8>,
register_width: RegisterWidth,
dst: GeneralReg,
offset: i32,
);
fn movzx_reg_base32(
buf: &mut Vec<'_, u8>,
register_width: RegisterWidth,
dst: GeneralReg,
offset: i32,
);
fn mov_freg64_stack32(buf: &mut Vec<'_, u8>, dst: FloatReg, offset: i32);
fn mov_reg64_stack32(buf: &mut Vec<'_, u8>, dst: GeneralReg, offset: i32);
@ -4075,10 +4084,12 @@ impl<
}
IntWidth::I16 | IntWidth::U16 => {
let dst_reg = storage_manager.claim_general_reg(buf, &dst);
ASM::xor_reg64_reg64_reg64(buf, dst_reg, dst_reg, dst_reg);
ASM::mov_reg16_mem16_offset32(buf, dst_reg, ptr_reg, offset);
}
IntWidth::I8 | IntWidth::U8 => {
let dst_reg = storage_manager.claim_general_reg(buf, &dst);
ASM::xor_reg64_reg64_reg64(buf, dst_reg, dst_reg, dst_reg);
ASM::mov_reg8_mem8_offset32(buf, dst_reg, ptr_reg, offset);
}
},
@ -4093,6 +4104,8 @@ impl<
Builtin::Bool => {
// the same as an 8-bit integer
let dst_reg = storage_manager.claim_general_reg(buf, &dst);
ASM::xor_reg64_reg64_reg64(buf, dst_reg, dst_reg, dst_reg);
ASM::mov_reg8_mem8_offset32(buf, dst_reg, ptr_reg, offset);
}
Builtin::Decimal => {

View file

@ -23,6 +23,8 @@ use RegStorage::*;
use StackStorage::*;
use Storage::*;
use super::RegisterWidth;
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum RegStorage<GeneralReg: RegTrait, FloatReg: RegTrait> {
General(GeneralReg),
@ -343,10 +345,19 @@ impl<
sign_extend,
}) => {
let reg = self.get_general_reg(buf);
let register_width = match size {
8 => RegisterWidth::W64,
4 => RegisterWidth::W32,
2 => RegisterWidth::W16,
1 => RegisterWidth::W8,
_ => internal_error!("Invalid size: {size}"),
};
if sign_extend {
ASM::movsx_reg64_base32(buf, reg, base_offset, size as u8);
ASM::movsx_reg_base32(buf, register_width, reg, base_offset);
} else {
ASM::movzx_reg64_base32(buf, reg, base_offset, size as u8);
ASM::movzx_reg_base32(buf, register_width, reg, base_offset);
}
self.general_used_regs.push((reg, *sym));
self.symbol_storage_map.insert(*sym, Reg(General(reg)));
@ -469,10 +480,18 @@ impl<
}) => {
debug_assert!(*size <= 8);
let register_width = match size {
8 => RegisterWidth::W64,
4 => RegisterWidth::W32,
2 => RegisterWidth::W16,
1 => RegisterWidth::W8,
_ => internal_error!("Invalid size: {size}"),
};
if *sign_extend {
ASM::movsx_reg64_base32(buf, reg, *base_offset, *size as u8)
ASM::movsx_reg_base32(buf, register_width, reg, *base_offset)
} else {
ASM::movzx_reg64_base32(buf, reg, *base_offset, *size as u8)
ASM::movzx_reg_base32(buf, register_width, reg, *base_offset)
}
}
Stack(Complex { size, .. }) => {

View file

@ -1687,29 +1687,39 @@ impl Assembler<X86_64GeneralReg, X86_64FloatReg> for X86_64Assembler {
}
#[inline(always)]
fn movsx_reg64_base32(buf: &mut Vec<'_, u8>, dst: X86_64GeneralReg, offset: i32, size: u8) {
debug_assert!(size <= 8);
match size {
8 => Self::mov_reg64_base32(buf, dst, offset),
4 => movsx_reg64_base32_offset32(buf, dst, X86_64GeneralReg::RBP, offset),
2 => movsx_reg64_base16_offset32(buf, dst, X86_64GeneralReg::RBP, offset),
1 => movsx_reg64_base8_offset32(buf, dst, X86_64GeneralReg::RBP, offset),
_ => internal_error!("Invalid size for sign extension: {size}"),
fn movsx_reg_base32(
buf: &mut Vec<'_, u8>,
register_width: RegisterWidth,
dst: X86_64GeneralReg,
offset: i32,
) {
use RegisterWidth::*;
match register_width {
W64 => Self::mov_reg64_base32(buf, dst, offset),
W32 => movsx_reg64_base32_offset32(buf, dst, X86_64GeneralReg::RBP, offset),
W16 => movsx_reg64_base16_offset32(buf, dst, X86_64GeneralReg::RBP, offset),
W8 => movsx_reg64_base8_offset32(buf, dst, X86_64GeneralReg::RBP, offset),
}
}
#[inline(always)]
fn movzx_reg64_base32(buf: &mut Vec<'_, u8>, dst: X86_64GeneralReg, offset: i32, size: u8) {
debug_assert!(size <= 8);
match size {
8 => Self::mov_reg64_base32(buf, dst, offset),
4 => {
fn movzx_reg_base32(
buf: &mut Vec<'_, u8>,
register_width: RegisterWidth,
dst: X86_64GeneralReg,
offset: i32,
) {
use RegisterWidth::*;
match register_width {
W64 => Self::mov_reg64_base32(buf, dst, offset),
W32 => {
// The Intel documentation (3.4.1.1 General-Purpose Registers in 64-Bit Mode in manual Basic Architecture))
// 32-bit operands generate a 32-bit result, zero-extended to a 64-bit result in the destination general-purpose register.
Self::mov_reg64_base32(buf, dst, offset)
}
2 => movzx_reg64_base16_offset32(buf, dst, X86_64GeneralReg::RBP, offset),
1 => movzx_reg64_base8_offset32(buf, dst, X86_64GeneralReg::RBP, offset),
_ => internal_error!("Invalid size for zero extension: {size}"),
W16 => movzx_reg64_base16_offset32(buf, dst, X86_64GeneralReg::RBP, offset),
W8 => movzx_reg64_base8_offset32(buf, dst, X86_64GeneralReg::RBP, offset),
}
}