1 use cranelift_codegen::ir; 2 use cranelift_codegen::ir::InstBuilder; 3 4 /// Returns the Cranelift type used to represent all of the following: 5 /// - wasm values of type `(ref null $ct)` and `(ref $ct)` 6 /// - equivalently: runtime values of type `Option<VMContObj>` and `VMContObj` 7 /// Note that a `VMContObj` is a fat pointer consisting of a pointer to 8 /// `VMContRef` and a pointer-sized revision counter. We represent this as 2 words 9 /// (pointer and usize). 10 pub fn fatpointer_type(env: &crate::func_environ::FuncEnvironment) -> ir::Type { 11 let ptr_bits = env.pointer_type().bits(); 12 ir::Type::int((2 * ptr_bits).try_into().unwrap()).unwrap() 13 } 14 15 /// Turns a (possibly null) reference to a continuation object into a tuple 16 /// (revision, contref_ptr). If `contobj` denotes a wasm null reference, the 17 /// contref_ptr part will be a null pointer. 18 pub(crate) fn deconstruct<'a>( 19 env: &mut crate::func_environ::FuncEnvironment<'a>, 20 pos: &mut cranelift_codegen::cursor::FuncCursor, 21 contobj: ir::Value, 22 ) -> (ir::Value, ir::Value) { 23 debug_assert_eq!(pos.func.dfg.value_type(contobj), fatpointer_type(env)); 24 let ptr_ty = env.pointer_type(); 25 let ptr_bits = ptr_ty.bits(); 26 27 let contref = pos.ins().ireduce(ptr_ty, contobj); 28 let shifted = pos.ins().ushr_imm(contobj, i64::from(ptr_bits)); 29 let revision_counter = pos.ins().ireduce(ptr_ty, shifted); 30 31 (revision_counter, contref) 32 } 33 34 /// Constructs a continuation object from a given contref and revision pointer. 35 /// The contref_addr may be 0, to indicate that we want to build a wasm null reference. 36 pub(crate) fn construct<'a>( 37 env: &mut crate::func_environ::FuncEnvironment<'a>, 38 pos: &mut cranelift_codegen::cursor::FuncCursor, 39 revision_counter: ir::Value, 40 contref_addr: ir::Value, 41 ) -> ir::Value { 42 let ptr_ty = env.pointer_type(); 43 let ptr_bits = ptr_ty.bits(); 44 let fat_ptr_ty = fatpointer_type(env); 45 46 debug_assert_eq!(pos.func.dfg.value_type(contref_addr), ptr_ty); 47 debug_assert_eq!(pos.func.dfg.value_type(revision_counter), ptr_ty); 48 49 let contref_addr = pos.ins().uextend(fat_ptr_ty, contref_addr); 50 let revision_counter = pos.ins().uextend(fat_ptr_ty, revision_counter); 51 let shifted_counter = pos.ins().ishl_imm(revision_counter, i64::from(ptr_bits)); 52 let contobj = pos.ins().bor(shifted_counter, contref_addr); 53 54 contobj 55 } 56