From 75e2007642c285b9552cda1b1742499a62916cd4 Mon Sep 17 00:00:00 2001 From: Lukas Diekmann Date: Mon, 12 Feb 2024 11:08:18 +0000 Subject: [PATCH 1/2] Process ptradd instructions and global operands. Add processing of AOT PtrAdd instructions. Since the JIT PtrAdd instruction is limited to 32 bit offsets, do the conversion here and return an error in case of a failure so we can abort the trace. While we are here, handle global operands by emitting a LoadGlobal instruction and replacing the global operand with an instruction operand referencing the just emitted instruction. --- ykrt/src/compile/jitc_yk/aot_ir.rs | 18 ++++++++++++ ykrt/src/compile/jitc_yk/jit_ir.rs | 18 +++++++----- ykrt/src/compile/jitc_yk/trace_builder.rs | 36 ++++++++++++++++++++++- 3 files changed, 63 insertions(+), 9 deletions(-) diff --git a/ykrt/src/compile/jitc_yk/aot_ir.rs b/ykrt/src/compile/jitc_yk/aot_ir.rs index 2e5d5ae89..446c2b276 100644 --- a/ykrt/src/compile/jitc_yk/aot_ir.rs +++ b/ykrt/src/compile/jitc_yk/aot_ir.rs @@ -595,6 +595,10 @@ pub(crate) struct IntegerType { } impl IntegerType { + pub(crate) fn num_bits(&self) -> u32 { + self.num_bits + } + fn const_to_str(&self, c: &Constant) -> String { // FIXME: For now we just handle common integer types, but eventually we will need to // implement printing of aribitrarily-sized (in bits) integers. Consider using a bigint @@ -768,6 +772,12 @@ pub(crate) struct Constant { bytes: Vec, } +impl Constant { + pub(crate) fn bytes(&self) -> &[u8] { + &self.bytes + } +} + impl IRDisplay for Constant { fn to_str(&self, m: &Module) -> String { m.types[self.type_idx].const_to_str(self) @@ -899,6 +909,14 @@ impl Module { &self.types[instr.type_idx] } + pub(crate) fn constant(&self, co: &ConstantOperand) -> &Constant { + &self.consts[co.const_idx] + } + + pub(crate) fn const_type(&self, c: &Constant) -> &Type { + &self.types[c.type_idx] + } + // FIXME: rename this to `is_def()`, which we've decided is a beter name. // FIXME: also move this to the `Instruction` type. fn instr_generates_value(&self, i: &Instruction) -> bool { diff --git a/ykrt/src/compile/jitc_yk/jit_ir.rs b/ykrt/src/compile/jitc_yk/jit_ir.rs index 8c935cb5e..694bf0aaf 100644 --- a/ykrt/src/compile/jitc_yk/jit_ir.rs +++ b/ykrt/src/compile/jitc_yk/jit_ir.rs @@ -340,18 +340,12 @@ impl LoadArgInstruction { pub struct LoadGlobalInstruction { /// The pointer to load from. global_idx: GlobalIdx, - /// The type of the pointee. - ty_idx: TypeIdx, } impl LoadGlobalInstruction { - pub(crate) fn new( - global_idx: aot_ir::GlobalIdx, - ty_idx: TypeIdx, - ) -> Result { + pub(crate) fn new(global_idx: aot_ir::GlobalIdx) -> Result { Ok(Self { global_idx: GlobalIdx::from_aot(global_idx)?, - ty_idx, }) } } @@ -380,7 +374,7 @@ pub struct CallInstruction { impl fmt::Display for CallInstruction { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "LoadArg") + write!(f, "Call") } } @@ -520,9 +514,17 @@ impl PtrAddInstruction { let ptr = self.ptr; ptr.get() } + fn offset(&self) -> u32 { self.off } + + pub(crate) fn new(ptr: Operand, off: u32) -> Self { + Self { + ptr: PackedOperand::new(&ptr), + off, + } + } } impl fmt::Display for PtrAddInstruction { diff --git a/ykrt/src/compile/jitc_yk/trace_builder.rs b/ykrt/src/compile/jitc_yk/trace_builder.rs index 2f5d584eb..718974d81 100644 --- a/ykrt/src/compile/jitc_yk/trace_builder.rs +++ b/ykrt/src/compile/jitc_yk/trace_builder.rs @@ -96,6 +96,7 @@ impl<'a> TraceBuilder<'a> { aot_ir::Opcode::Load => self.handle_load(inst), aot_ir::Opcode::Call => self.handle_call(inst), aot_ir::Opcode::Store => self.handle_store(inst), + aot_ir::Opcode::PtrAdd => self.handle_ptradd(inst), _ => todo!("{:?}", inst), }?; @@ -129,6 +130,15 @@ impl<'a> TraceBuilder<'a> { let instridx = self.local_map[lvo.instr_id()]; jit_ir::Operand::Local(instridx) } + aot_ir::Operand::Constant(_co) => { + todo!() + } + aot_ir::Operand::Global(go) => { + let load = jit_ir::LoadGlobalInstruction::new(go.index())?; + let idx = self.next_instr_id()?; + self.jit_mod.push(load.into()); + jit_ir::Operand::Local(idx) + } aot_ir::Operand::Unimplemented(_) => { // FIXME: for now we push an arbitrary constant. let constidx = self @@ -149,7 +159,7 @@ impl<'a> TraceBuilder<'a> { let ty_idx = jit_ir::TypeIdx::from_aot(inst.type_idx())?; if let aot_ir::Operand::Global(go) = inst.operand(0) { // Generate a special load instruction for globals. - Ok(jit_ir::LoadGlobalInstruction::new(go.index(), ty_idx)?.into()) + Ok(jit_ir::LoadGlobalInstruction::new(go.index())?.into()) } else { let jit_op = self.handle_operand(inst.operand(0))?; Ok(jit_ir::LoadInstruction::new(jit_op, ty_idx).into()) @@ -181,6 +191,30 @@ impl<'a> TraceBuilder<'a> { } } + fn handle_ptradd( + &mut self, + inst: &aot_ir::Instruction, + ) -> Result { + let target = self.handle_operand(inst.operand(0))?; + if let aot_ir::Operand::Constant(co) = inst.operand(1) { + let c = self.aot_mod.constant(co); + if let aot_ir::Type::Integer(it) = self.aot_mod.const_type(c) { + // Convert the offset into a 32 bit value, as that is the maximum we can fit into + // the jit_ir::PtrAddInstruction. + let offset: u32 = match it.num_bits() { + 64 => u64::from_ne_bytes(c.bytes()[0..8].try_into().unwrap()) + .try_into() + .map_err(|_| { + CompilationError::Unrecoverable("ptradd offset too big".into()) + }), + _ => panic!(), + }?; + return Ok(jit_ir::PtrAddInstruction::new(target, offset).into()); + }; + } + panic!() + } + /// Entry point for building an IR trace. /// /// Consumes the trace builder, returning a JIT module. From 9b58be85b4db75b0e04b6a977a3ce183d0dc25bc Mon Sep 17 00:00:00 2001 From: Lukas Diekmann Date: Mon, 19 Feb 2024 15:04:15 +0000 Subject: [PATCH 2/2] Fix test. --- ykrt/src/compile/jitc_yk/jit_ir.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ykrt/src/compile/jitc_yk/jit_ir.rs b/ykrt/src/compile/jitc_yk/jit_ir.rs index 694bf0aaf..300d49094 100644 --- a/ykrt/src/compile/jitc_yk/jit_ir.rs +++ b/ykrt/src/compile/jitc_yk/jit_ir.rs @@ -677,7 +677,7 @@ mod tests { assert_eq!(mem::size_of::(), 7); assert_eq!(mem::size_of::(), 4); assert_eq!(mem::size_of::(), 6); - assert_eq!(mem::size_of::(), 6); + assert_eq!(mem::size_of::(), 3); assert_eq!(mem::size_of::(), 6); assert_eq!(mem::size_of::(), 6); assert!(mem::size_of::() <= mem::size_of::());