diff --git a/crates/cranelift/src/alias_region.rs b/crates/cranelift/src/alias_region.rs index a7653858a72a..2aee704cf60c 100644 --- a/crates/cranelift/src/alias_region.rs +++ b/crates/cranelift/src/alias_region.rs @@ -1631,8 +1631,8 @@ impl AliasRegions> { ) } - /// Load a component instance's flags from the `VMComponentContext`. - pub fn vmcomponent_instance_flags( + /// Load a component instance's `may_leave` flag from the `VMComponentContext`. + pub fn vmcomponent_instance_may_leave( &mut self, cursor: &mut FuncCursor<'_>, vmctx: ir::Value, @@ -1643,7 +1643,7 @@ impl AliasRegions> { ir::types::I32, ir::MemFlagsData::trusted(), vmctx, - self.offsets.instance_flags(instance), + self.offsets.may_leave(instance), ) } } diff --git a/crates/cranelift/src/compiler/component.rs b/crates/cranelift/src/compiler/component.rs index a0a6836e7a0c..74d706294308 100644 --- a/crates/cranelift/src/compiler/component.rs +++ b/crates/cranelift/src/compiler/component.rs @@ -1113,9 +1113,8 @@ impl<'a> TrampolineCompiler<'a> { // run_destructor_block: // ;; test may_leave, but only if the component instances // ;; differ - // flags = load.i32 vmctx+$instance_flags_offset - // masked = band flags, $FLAG_MAY_LEAVE - // trapz masked, $TRAP_CANNOT_LEAVE_COMPONENT + // may_leave = load.i32 vmctx+$instance_flags_offset + // trapz may_leave, $TRAP_CANNOT_LEAVE_COMPONENT // // ;; set may_block to false, saving the old value to restore // ;; later, but only if the component instances differ and @@ -1527,17 +1526,13 @@ impl<'a> TrampolineCompiler<'a> { fn check_may_leave_instance(&mut self, instance: RuntimeComponentInstanceIndex) { let vmctx = self.builder.func.dfg.block_params(self.block0)[0]; - let flags = self.alias_regions.vmcomponent_instance_flags( + let may_leave = self.alias_regions.vmcomponent_instance_may_leave( &mut self.builder.cursor(), vmctx, instance, ); - let may_leave_bit = self - .builder - .ins() - .band_imm_u(flags, i64::from(FLAG_MAY_LEAVE)); let (mut traps, builder) = self.traps(); - traps.trapz(builder, may_leave_bit, TRAP_CANNOT_LEAVE_COMPONENT); + traps.trapz(builder, may_leave, TRAP_CANNOT_LEAVE_COMPONENT); } fn traps( diff --git a/crates/environ/src/component/vmcomponent_offsets.rs b/crates/environ/src/component/vmcomponent_offsets.rs index 4983314fc5d8..9c5f3b330803 100644 --- a/crates/environ/src/component/vmcomponent_offsets.rs +++ b/crates/environ/src/component/vmcomponent_offsets.rs @@ -4,7 +4,7 @@ // magic: u32, // builtins: &'static VMComponentBuiltins, // limits: *const VMStoreContext, -// flags: [VMGlobalDefinition; component.num_runtime_component_instances], +// may_leave: [VMGlobalDefinition; component.num_runtime_component_instances], // task_may_block: u32, // trampoline_func_refs: [VMFuncRef; component.num_trampolines], // unsafe_intrinsics: [VMFuncRef; component.num_unsafe_intrinsics], @@ -26,10 +26,6 @@ use crate::component::*; /// double-checked on `VMComponentContext::from_opaque`. pub const VMCOMPONENT_MAGIC: u32 = u32::from_le_bytes(*b"comp"); -/// Flag for the `VMComponentContext::flags` field which corresponds to the -/// canonical ABI flag `may_leave` -pub const FLAG_MAY_LEAVE: i32 = 1 << 0; - /// Runtime offsets within a `VMComponentContext` for a specific component. #[derive(Debug, Clone, Copy)] pub struct VMComponentOffsets

{ @@ -63,7 +59,7 @@ pub struct VMComponentOffsets

{ magic: u32, builtins: u32, vm_store_context: u32, - flags: u32, + may_leave: u32, task_may_block: u32, trampoline_func_refs: u32, intrinsic_func_refs: u32, @@ -132,7 +128,7 @@ impl VMComponentOffsets

{ magic: 0, builtins: 0, vm_store_context: 0, - flags: 0, + may_leave: 0, task_may_block: 0, trampoline_func_refs: 0, intrinsic_func_refs: 0, @@ -176,7 +172,7 @@ impl VMComponentOffsets

{ size(builtins) = ret.ptr.size(), size(vm_store_context) = ret.ptr.size(), align(16), - size(flags) = cmul(ret.num_runtime_component_instances, ret.ptr.size_of_vmglobal_definition()), + size(may_leave) = cmul(ret.num_runtime_component_instances, ret.ptr.size_of_vmglobal_definition()), size(task_may_block) = ret.ptr.size_of_vmglobal_definition(), align(u32::from(ret.ptr.size())), size(trampoline_func_refs) = cmul(ret.num_trampolines, ret.ptr.size_of_vm_func_ref()), @@ -218,11 +214,11 @@ impl VMComponentOffsets

{ self.builtins } - /// The offset of the `flags` field. + /// The offset of the `may_leave` flag for the given component instance. #[inline] - pub fn instance_flags(&self, index: RuntimeComponentInstanceIndex) -> u32 { + pub fn may_leave(&self, index: RuntimeComponentInstanceIndex) -> u32 { assert!(index.as_u32() < self.num_runtime_component_instances); - self.flags + index.as_u32() * u32::from(self.ptr.size_of_vmglobal_definition()) + self.may_leave + index.as_u32() * u32::from(self.ptr.size_of_vmglobal_definition()) } /// The offset of the `task_may_block` field. diff --git a/crates/environ/src/fact/trampoline.rs b/crates/environ/src/fact/trampoline.rs index d046a998b76c..4539ad13ecb8 100644 --- a/crates/environ/src/fact/trampoline.rs +++ b/crates/environ/src/fact/trampoline.rs @@ -16,13 +16,12 @@ //! can be somewhat arbitrary, an intentional decision. use crate::component::{ - CanonicalAbiInfo, ComponentTypesBuilder, FLAG_MAY_LEAVE, FixedEncoding as FE, FlatType, - InterfaceType, MAX_FLAT_ASYNC_PARAMS, MAX_FLAT_PARAMS, PREPARE_ASYNC_NO_RESULT, - PREPARE_ASYNC_WITH_RESULT, START_FLAG_ASYNC_CALLEE, StringEncoding, Transcode, - TypeComponentLocalErrorContextTableIndex, TypeEnumIndex, TypeFixedLengthListIndex, - TypeFlagsIndex, TypeFutureTableIndex, TypeListIndex, TypeMapIndex, TypeOptionIndex, - TypeRecordIndex, TypeResourceTableIndex, TypeResultIndex, TypeStreamTableIndex, TypeTupleIndex, - TypeVariantIndex, VariantInfo, + CanonicalAbiInfo, ComponentTypesBuilder, FixedEncoding as FE, FlatType, InterfaceType, + MAX_FLAT_ASYNC_PARAMS, MAX_FLAT_PARAMS, PREPARE_ASYNC_NO_RESULT, PREPARE_ASYNC_WITH_RESULT, + START_FLAG_ASYNC_CALLEE, StringEncoding, Transcode, TypeComponentLocalErrorContextTableIndex, + TypeEnumIndex, TypeFixedLengthListIndex, TypeFlagsIndex, TypeFutureTableIndex, TypeListIndex, + TypeMapIndex, TypeOptionIndex, TypeRecordIndex, TypeResourceTableIndex, TypeResultIndex, + TypeStreamTableIndex, TypeTupleIndex, TypeVariantIndex, VariantInfo, }; use crate::fact::signature::Signature; use crate::fact::transcode::Transcoder; @@ -701,9 +700,9 @@ impl<'a, 'b> Compiler<'a, 'b> { .map(|(i, ty)| (i as u32, *ty)) .collect::>(); - self.set_flag(adapter.lift.flags, FLAG_MAY_LEAVE, false); + let saved = self.clear_may_leave(adapter.lift.flags); self.translate_params(adapter, ¶m_locals); - self.set_flag(adapter.lift.flags, FLAG_MAY_LEAVE, true); + self.restore_may_leave(adapter.lift.flags, saved); self.finish(); } @@ -727,7 +726,7 @@ impl<'a, 'b> Compiler<'a, 'b> { .map(|(i, ty)| (i as u32, *ty)) .collect::>(); - self.set_flag(adapter.lower.flags, FLAG_MAY_LEAVE, false); + let saved = self.clear_may_leave(adapter.lower.flags); // Note that we pass `param_locals` as _both_ the `param_locals` and // `result_locals` parameters to `translate_results`. That's because // the _parameters_ to `task.return` are actually the _results_ that the @@ -739,7 +738,7 @@ impl<'a, 'b> Compiler<'a, 'b> { // the import is lowered async, in which case `translate_results` will // use that pointer to store the results. self.translate_results(adapter, ¶m_locals, ¶m_locals); - self.set_flag(adapter.lower.flags, FLAG_MAY_LEAVE, true); + self.restore_may_leave(adapter.lower.flags, saved); self.finish() } @@ -763,11 +762,12 @@ impl<'a, 'b> Compiler<'a, 'b> { // This inserts the initial check required by `canon_lower` that the // caller instance can be left and additionally checks the // flags on the callee if necessary whether it can be entered. - self.trap_if_not_flag( - adapter.lower.flags, - FLAG_MAY_LEAVE, - Trap::CannotLeaveComponent, - ); + // + // The loaded `may_leave` value is saved into `saved_lower_may_leave` + // so that it can be restored after results are translated below + // without reloading the global. + let saved_lower_may_leave = + self.trap_if_not_may_leave(adapter.lower.flags, Trap::CannotLeaveComponent); let old_task_may_block = if self.module.tunables.concurrency_support { // Save, clear, and later restore the `may_block` field. @@ -823,8 +823,8 @@ impl<'a, 'b> Compiler<'a, 'b> { None }; - // Perform the translation of arguments. Note that `FLAG_MAY_LEAVE` is - // cleared around this invocation for the callee as per the + // Perform the translation of arguments. Note that the `may_leave` flag + // is cleared around this invocation for the callee as per the // `canon_lift` definition in the spec. Additionally note that the // precise ordering of traps here is not required since internal state // is not visible to either instance and a trap will "lock down" both @@ -832,10 +832,32 @@ impl<'a, 'b> Compiler<'a, 'b> { // reorder lifts/lowers and flags and such as is necessary and // convenient here. // - // TODO: if translation doesn't actually call any functions in either - // instance then there's no need to set/clear the flag here and that can - // be optimized away. - self.set_flag(adapter.lift.flags, FLAG_MAY_LEAVE, false); + // The clear-and-restore is structured (a constant `0` store to clear, + // then a store of the saved original value to restore) so that if + // translation doesn't actually call any functions in either instance + // then a future dead-store elimination pass in Cranelift can remove all + // the flag juggling entirely (other than trapping when `!may_leave`): + // + // may_leave = load vmctx+MAY_LEAVE_OFFSET ;; (0) + // trapz may_leave + // + // ... + // + // zero = iconst 0 + // store zero, vmctx+MAY_LEAVE_OFFSET ;; (1) + // + // ... + // + // store may_leave, vmctx+MAY_LEAVE_OFFSET ;; (2) + // + // First, the dead-store elimination pass will see that the the store at + // (1) is dead and remove it. Then, the idempotent-store eliminator will + // recognize that the store at (2) is storing the same value that the + // memory location already contains and it will also be removed. The + // more we can reuse locals to make this idempotency obvious, rather + // than force Cranelift's optimizer to rediscover this information, the + // better. + let saved_lift_may_leave = self.clear_may_leave(adapter.lift.flags); let param_locals = lower_sig .params .iter() @@ -843,7 +865,7 @@ impl<'a, 'b> Compiler<'a, 'b> { .map(|(i, ty)| (i as u32, *ty)) .collect::>(); self.translate_params(adapter, ¶m_locals); - self.set_flag(adapter.lift.flags, FLAG_MAY_LEAVE, true); + self.restore_may_leave(adapter.lift.flags, saved_lift_may_leave); // With all the arguments on the stack the actual target function is // now invoked. The core wasm results of the function are then placed @@ -882,12 +904,9 @@ impl<'a, 'b> Compiler<'a, 'b> { // order of everything doesn't matter since intermediate states cannot // be witnessed, hence the setting of flags here to encapsulate both // liftings and lowerings. - // - // TODO: like above the management of the `MAY_LEAVE` flag can probably - // be elided here for "simple" results. - self.set_flag(adapter.lower.flags, FLAG_MAY_LEAVE, false); + self.set_may_leave_false(adapter.lower.flags); self.translate_results(adapter, ¶m_locals, &result_locals); - self.set_flag(adapter.lower.flags, FLAG_MAY_LEAVE, true); + self.restore_may_leave(adapter.lower.flags, saved_lower_may_leave); // And finally post-return state is handled here once all results/etc // are all translated. @@ -3575,26 +3594,58 @@ impl<'a, 'b> Compiler<'a, 'b> { } } - fn trap_if_not_flag(&mut self, flags_global: GlobalIndex, flag_to_test: i32, trap: Trap) { + /// Loads the `may_leave` flag for the given instance, traps with `trap` if + /// it is not set, and returns a temporary local holding the loaded value + /// so that it can later be restored with `restore_may_leave` without + /// reloading the global. + /// + /// The `may_leave` flag is a boolean (0 or 1) so no masking is required. + fn trap_if_not_may_leave(&mut self, flags_global: GlobalIndex, trap: Trap) -> TempLocal { self.instruction(GlobalGet(flags_global.as_u32())); - self.instruction(I32Const(flag_to_test)); - self.instruction(I32And); + // Save the flag's value (known to be `true` whenever the trap below is + // not taken) into a temporary for later restoration. + let saved = self.local_tee_new_tmp(ValType::I32); self.instruction(I32Eqz); self.instruction(If(BlockType::Empty)); self.trap(trap); self.instruction(End); + saved } - fn set_flag(&mut self, flags_global: GlobalIndex, flag_to_set: i32, value: bool) { + /// Saves the current value of the `may_leave` flag into a fresh temporary + /// local (returned) and then clears the flag to `false`. + fn clear_may_leave(&mut self, flags_global: GlobalIndex) -> TempLocal { self.instruction(GlobalGet(flags_global.as_u32())); - if value { - self.instruction(I32Const(flag_to_set)); - self.instruction(I32Or); - } else { - self.instruction(I32Const(!flag_to_set)); - self.instruction(I32And); - } + let saved = self.local_set_new_tmp(ValType::I32); + self.set_may_leave_false(flags_global); + saved + } + + /// Sets the `may_leave` flag to `false` by storing a constant `0`. + /// + /// Since there is only a single flag there is no need to reload the global + /// and mask: storing `0` is sufficient. + fn set_may_leave_false(&mut self, flags_global: GlobalIndex) { + self.instruction(I32Const(0)); + self.instruction(GlobalSet(flags_global.as_u32())); + } + + /// Restores the `may_leave` flag to the value previously saved in `saved` + /// (via `clear_may_leave` or `trap_if_not_may_leave`) and frees the + /// temporary local. + /// + /// Storing the previously-loaded value (rather than reloading the global + /// and or-ing in the flag bit) makes it clear in the generated CLIF that + /// the same value that was there before is being written back. Combined + /// with the constant `0` store in `set_may_leave_false`, this lets a future + /// dead-store-elimination pass remove the clear-to-`false` store which will + /// then allow our idempotent-store elimination to remove this restore for + /// adapters whose body never touches the flag (e.g. simple inlined + /// callees). + fn restore_may_leave(&mut self, flags_global: GlobalIndex, saved: TempLocal) { + self.instruction(LocalGet(saved.idx)); self.instruction(GlobalSet(flags_global.as_u32())); + self.free_temp_local(saved); } fn assert_aligned(&mut self, ty: &InterfaceType, mem: &Memory) { diff --git a/crates/wasmtime/src/runtime/vm/component.rs b/crates/wasmtime/src/runtime/vm/component.rs index e088657a6cec..de21c6738bfd 100644 --- a/crates/wasmtime/src/runtime/vm/component.rs +++ b/crates/wasmtime/src/runtime/vm/component.rs @@ -365,8 +365,8 @@ impl ComponentInstance { #[inline] pub fn instance_flags(&self, instance: RuntimeComponentInstanceIndex) -> InstanceFlags { unsafe { - let ptr = self - .vmctx_plus_offset_raw::(self.offsets.instance_flags(instance)); + let ptr = + self.vmctx_plus_offset_raw::(self.offsets.may_leave(instance)); InstanceFlags(SendSyncPtr::new(ptr)) } } @@ -704,9 +704,9 @@ impl ComponentInstance { let i = RuntimeComponentInstanceIndex::from_u32(i); let mut def = VMGlobalDefinition::new(); // SAFETY: this is a valid initialization of all globals which are - // 32-bit values. + // 32-bit values. The `may_leave` flag starts out `true`. unsafe { - *def.as_i32_mut() = FLAG_MAY_LEAVE; + *def.as_i32_mut() = 1; self.instance_flags(i).as_raw().write(def); } } @@ -1062,17 +1062,13 @@ impl InstanceFlags { #[inline] pub unsafe fn may_leave(&self) -> bool { - unsafe { *self.as_raw().as_ref().as_i32() & FLAG_MAY_LEAVE != 0 } + unsafe { *self.as_raw().as_ref().as_i32() != 0 } } #[inline] pub unsafe fn set_may_leave(&mut self, val: bool) { unsafe { - if val { - *self.as_raw().as_mut().as_i32_mut() |= FLAG_MAY_LEAVE; - } else { - *self.as_raw().as_mut().as_i32_mut() &= !FLAG_MAY_LEAVE; - } + *self.as_raw().as_mut().as_i32_mut() = val as i32; } } diff --git a/tests/disas/component-may-leave-without-signals-based-traps.wat b/tests/disas/component-may-leave-without-signals-based-traps.wat index ef878974ae3f..d9834361eaea 100644 --- a/tests/disas/component-may-leave-without-signals-based-traps.wat +++ b/tests/disas/component-may-leave-without-signals-based-traps.wat @@ -25,9 +25,9 @@ ;; movq 8(%rcx), %rcx ;; movq %rcx, 0x38(%rax) ;; movl 0x20(%rdi), %eax -;; testl $1, %eax -;; je 0x13e -;; fe: movq 8(%rdi), %rax +;; testl %eax, %eax +;; je 0x13b +;; fb: movq 8(%rdi), %rax ;; movq (%rax), %rax ;; xorl %ecx, %ecx ;; movl %ecx, %esi @@ -36,21 +36,21 @@ ;; movl %ecx, %ecx ;; callq *%rax ;; cmpq $-1, %rax -;; je 0x129 -;; 11c: movq (%rsp), %rbx +;; je 0x126 +;; 119: movq (%rsp), %rbx ;; addq $0x10, %rsp ;; movq %rbp, %rsp ;; popq %rbp ;; retq -;; 129: movq %rbx, %rsi -;; 12c: movq 0x10(%rsi), %rax -;; 130: movq 0x148(%rax), %rax -;; 137: movq %rbx, %rdi -;; 13a: callq *%rax -;; 13c: ud2 -;; 13e: movl $0x17, %esi -;; 143: movq %rbx, %rdi -;; 146: callq 0x6a -;; 14b: movq %rbx, %rdi -;; 14e: callq 0x9b -;; 153: ud2 +;; 126: movq %rbx, %rsi +;; 129: movq 0x10(%rsi), %rax +;; 12d: movq 0x148(%rax), %rax +;; 134: movq %rbx, %rdi +;; 137: callq *%rax +;; 139: ud2 +;; 13b: movl $0x17, %esi +;; 140: movq %rbx, %rdi +;; 143: callq 0x6a +;; 148: movq %rbx, %rdi +;; 14b: callq 0x9b +;; 150: ud2 diff --git a/tests/disas/component-model/direct-adapter-calls-inlining.wat b/tests/disas/component-model/direct-adapter-calls-inlining.wat index d990e66dc0dc..d5663715aa89 100644 --- a/tests/disas/component-model/direct-adapter-calls-inlining.wat +++ b/tests/disas/component-model/direct-adapter-calls-inlining.wat @@ -92,30 +92,25 @@ ;; @00ee v4 = load.i64 notrap aligned readonly can_move region2 v0+72 ;; v14 = load.i64 notrap aligned readonly can_move region3 v4+136 ;; v15 = load.i32 notrap aligned region4 v14 -;; v16 = iconst.i32 1 -;; v17 = band v15, v16 ; v16 = 1 ;; v13 = iconst.i32 0 -;; v19 = icmp eq v17, v13 ; v13 = 0 -;; brif v19, block9, block10 +;; v17 = icmp eq v15, v13 ; v13 = 0 +;; brif v17, block9, block10 ;; ;; block9: -;; v23 = load.i64 notrap aligned readonly can_move region6 v4+88 -;; v22 = load.i64 notrap aligned readonly can_move region5 v4+104 -;; v21 = iconst.i32 23 -;; try_call_indirect v23(v22, v4, v21), sig1, block11, [ context v4, default: block8(exn0) ] ; v21 = 23 +;; v21 = load.i64 notrap aligned readonly can_move region6 v4+88 +;; v20 = load.i64 notrap aligned readonly can_move region5 v4+104 +;; v19 = iconst.i32 23 +;; try_call_indirect v21(v20, v4, v19), sig1, block11, [ context v4, default: block8(exn0) ] ; v19 = 23 ;; ;; block11: ;; trap user12 ;; ;; block10: -;; v28 = load.i64 notrap aligned readonly can_move region7 v4+112 -;; v29 = load.i32 notrap aligned region4 v28 -;; v30 = iconst.i32 -2 -;; v31 = band v29, v30 ; v30 = -2 -;; store notrap aligned region4 v31, v28 -;; v61 = iconst.i32 1 -;; v62 = bor v29, v61 ; v61 = 1 -;; store notrap aligned region4 v62, v28 +;; v26 = load.i64 notrap aligned readonly can_move region7 v4+112 +;; v27 = load.i32 notrap aligned region4 v26 +;; v43 = iconst.i32 0 +;; store notrap aligned region4 v43, v26 ; v43 = 0 +;; store notrap aligned region4 v27, v26 ;; jump block13 ;; ;; block13: @@ -125,21 +120,17 @@ ;; jump block12 ;; ;; block12: -;; v42 = load.i32 notrap aligned region4 v14 -;; v63 = iconst.i32 -2 -;; v64 = band v42, v63 ; v63 = -2 -;; store notrap aligned region4 v64, v14 -;; v65 = iconst.i32 1 -;; v66 = bor v42, v65 ; v65 = 1 -;; store notrap aligned region4 v66, v14 +;; v44 = iconst.i32 0 +;; store notrap aligned region4 v44, v14 ; v44 = 0 +;; store.i32 notrap aligned region4 v15, v14 ;; jump block7 ;; ;; block7: ;; jump block4 ;; ;; block5: -;; v25 = iconst.i32 49 -;; call_indirect.i64 sig1, v23(v22, v4, v25) ; v25 = 49 +;; v23 = iconst.i32 49 +;; call_indirect.i64 sig1, v21(v20, v4, v23) ; v23 = 49 ;; trap user12 ;; ;; block4: @@ -152,6 +143,6 @@ ;; @00f0 jump block1 ;; ;; block1: -;; v53 = iconst.i32 1276 -;; @00f0 return v53 ; v53 = 1276 +;; v37 = iconst.i32 1276 +;; @00f0 return v37 ; v37 = 1276 ;; } diff --git a/tests/disas/component-model/direct-adapter-calls-x64.wat b/tests/disas/component-model/direct-adapter-calls-x64.wat index 3dcbe79db152..8dd507783d58 100644 --- a/tests/disas/component-model/direct-adapter-calls-x64.wat +++ b/tests/disas/component-model/direct-adapter-calls-x64.wat @@ -85,65 +85,60 @@ ;; movq %rsp, %rbp ;; movq 8(%rdi), %r10 ;; movq 0x18(%r10), %r10 -;; addq $0x50, %r10 +;; addq $0x60, %r10 ;; cmpq %rsp, %r10 -;; ja 0x147 -;; 79: subq $0x40, %rsp -;; movq %rbx, 0x10(%rsp) -;; movq %r12, 0x18(%rsp) -;; movq %r13, 0x20(%rsp) -;; movq %r14, 0x28(%rsp) -;; movq %r15, 0x30(%rsp) +;; ja 0x13e +;; 79: subq $0x50, %rsp +;; movq %rbx, 0x20(%rsp) +;; movq %r12, 0x28(%rsp) +;; movq %r13, 0x30(%rsp) +;; movq %r14, 0x38(%rsp) +;; movq %r15, 0x40(%rsp) ;; movq %rdi, (%rsp) ;; movq (%rsp), %rdi -;; movq 0x88(%rdi), %r8 -;; movl (%r8), %eax -;; movq %r8, 8(%rsp) -;; testl $1, %eax -;; je 0x115 -;; b8: movq (%rsp), %rdi +;; movq 0x88(%rdi), %rcx +;; movl (%rcx), %esi +;; movq %rcx, 0x10(%rsp) +;; testl %esi, %esi +;; movq %rsi, 8(%rsp) +;; je 0x10c +;; b9: movq (%rsp), %rdi ;; movq 0x70(%rdi), %rax ;; movl (%rax), %ecx -;; movq %rcx, %rsi -;; andl $0xfffffffe, %esi -;; movl %esi, (%rax) -;; orl $1, %ecx +;; movl $0, (%rax) ;; movl %ecx, (%rax) ;; movq 0x48(%rdi), %rdi ;; movq (%rsp), %rsi ;; callq 0 -;; ├─╼ exception frame offset: SP = FP - 0x40 -;; ╰─╼ exception handler: default handler, context at [SP+0x0], handler=0x12e -;; movq 8(%rsp), %r8 -;; movl (%r8), %ecx -;; movq %rcx, %rsi -;; andl $0xfffffffe, %esi -;; movl %esi, (%r8) -;; orl $1, %ecx -;; movl %ecx, (%r8) -;; movq 0x10(%rsp), %rbx -;; movq 0x18(%rsp), %r12 -;; movq 0x20(%rsp), %r13 -;; movq 0x28(%rsp), %r14 -;; movq 0x30(%rsp), %r15 -;; addq $0x40, %rsp +;; ├─╼ exception frame offset: SP = FP - 0x50 +;; ╰─╼ exception handler: default handler, context at [SP+0x0], handler=0x125 +;; movq 0x10(%rsp), %rcx +;; movl $0, (%rcx) +;; movq 8(%rsp), %rsi +;; movl %esi, (%rcx) +;; movq 0x20(%rsp), %rbx +;; movq 0x28(%rsp), %r12 +;; movq 0x30(%rsp), %r13 +;; movq 0x38(%rsp), %r14 +;; movq 0x40(%rsp), %r15 +;; addq $0x50, %rsp ;; movq %rbp, %rsp ;; popq %rbp ;; retq -;; 115: movq (%rsp), %rcx -;; 119: movq 0x58(%rcx), %rax -;; 11d: movq 0x68(%rcx), %rdi -;; 121: movl $0x17, %edx -;; 126: movq (%rsp), %rsi -;; 12a: callq *%rax -;; ├─╼ exception frame offset: SP = FP - 0x40 -;; ╰─╼ exception handler: default handler, context at [SP+0x0], handler=0x12e -;; 12c: ud2 -;; 12e: movq (%rsp), %rcx -;; 132: movq 0x58(%rcx), %rax -;; 136: movq 0x68(%rcx), %rdi -;; 13a: movl $0x31, %edx -;; 13f: movq (%rsp), %rsi -;; 143: callq *%rax -;; 145: ud2 -;; 147: ud2 +;; 10c: movq (%rsp), %rcx +;; 110: movq 0x58(%rcx), %rax +;; 114: movq 0x68(%rcx), %rdi +;; 118: movl $0x17, %edx +;; 11d: movq (%rsp), %rsi +;; 121: callq *%rax +;; ├─╼ exception frame offset: SP = FP - 0x50 +;; ╰─╼ exception handler: default handler, context at [SP+0x0], handler=0x125 +;; 123: ud2 +;; 125: movq (%rsp), %rcx +;; 129: movq 0x58(%rcx), %rax +;; 12d: movq 0x68(%rcx), %rdi +;; 131: movl $0x31, %edx +;; 136: movq (%rsp), %rsi +;; 13a: callq *%rax +;; 13c: ud2 +;; 13e: ud2 diff --git a/tests/disas/component-model/direct-adapter-calls.wat b/tests/disas/component-model/direct-adapter-calls.wat index 5e24a00ea01d..2dc06561d0f1 100644 --- a/tests/disas/component-model/direct-adapter-calls.wat +++ b/tests/disas/component-model/direct-adapter-calls.wat @@ -121,56 +121,47 @@ ;; block4: ;; @0080 v9 = load.i64 notrap aligned readonly can_move region2 v0+136 ;; @0080 v10 = load.i32 notrap aligned region3 v9 -;; @0082 v11 = iconst.i32 1 -;; @0084 v12 = band v10, v11 ; v11 = 1 ;; @0075 v4 = iconst.i32 0 -;; @0085 v14 = icmp eq v12, v4 ; v4 = 0 -;; @0086 brif v14, block7, block8 +;; @0084 v12 = icmp eq v10, v4 ; v4 = 0 +;; @0085 brif v12, block7, block8 ;; ;; block7: -;; @008a v18 = load.i64 notrap aligned readonly can_move region5 v0+88 -;; @008a v17 = load.i64 notrap aligned readonly can_move region4 v0+104 -;; @0088 v16 = iconst.i32 23 -;; @008a try_call_indirect v18(v17, v0, v16), sig0, block9, [ context v0, default: block6(exn0) ] ; v16 = 23 +;; @0089 v16 = load.i64 notrap aligned readonly can_move region5 v0+88 +;; @0089 v15 = load.i64 notrap aligned readonly can_move region4 v0+104 +;; @0087 v14 = iconst.i32 23 +;; @0089 try_call_indirect v16(v15, v0, v14), sig0, block9, [ context v0, default: block6(exn0) ] ; v14 = 23 ;; ;; block9: -;; @008c trap user12 +;; @008b trap user12 ;; ;; block8: -;; @008e v19 = load.i64 notrap aligned readonly can_move region6 v0+112 -;; @008e v20 = load.i32 notrap aligned region3 v19 -;; @0090 v21 = iconst.i32 -2 -;; @0092 v22 = band v20, v21 ; v21 = -2 -;; @0093 store notrap aligned region3 v22, v19 -;; v48 = iconst.i32 1 -;; v49 = bor v20, v48 ; v48 = 1 -;; @009c store notrap aligned region3 v49, v19 -;; @009e v29 = load.i64 notrap aligned readonly can_move region7 v0+72 -;; @009e try_call fn0(v29, v0, v2), sig1, block10(ret0), [ context v0, default: block6(exn0) ] -;; -;; block10(v30: i32): -;; @00a2 v32 = load.i32 notrap aligned region3 v9 -;; v50 = iconst.i32 -2 -;; v51 = band v32, v50 ; v50 = -2 -;; @00a7 store notrap aligned region3 v51, v9 -;; v52 = iconst.i32 1 -;; v53 = bor v32, v52 ; v52 = 1 -;; @00b0 store notrap aligned region3 v53, v9 -;; @00b2 jump block5(v30) +;; @008d v17 = load.i64 notrap aligned readonly can_move region6 v0+112 +;; @008d v18 = load.i32 notrap aligned region3 v17 +;; v30 = iconst.i32 0 +;; @0093 store notrap aligned region3 v30, v17 ; v30 = 0 +;; @0099 store notrap aligned region3 v18, v17 +;; @009b v22 = load.i64 notrap aligned readonly can_move region7 v0+72 +;; @009b try_call fn0(v22, v0, v2), sig1, block10(ret0), [ context v0, default: block6(exn0) ] +;; +;; block10(v23: i32): +;; v31 = iconst.i32 0 +;; @00a1 store notrap aligned region3 v31, v9 ; v31 = 0 +;; @00a7 store.i32 notrap aligned region3 v10, v9 +;; @00a9 jump block5(v23) ;; ;; block5(v6: i32): -;; @00b3 jump block2(v6) +;; @00aa jump block2(v6) ;; ;; block3: -;; v54 = load.i64 notrap aligned readonly can_move region5 v0+88 -;; v55 = load.i64 notrap aligned readonly can_move region4 v0+104 -;; @00b6 v41 = iconst.i32 49 -;; @00b8 call_indirect sig0, v54(v55, v0, v41) ; v41 = 49 -;; @00ba trap user12 +;; v32 = load.i64 notrap aligned readonly can_move region5 v0+88 +;; v33 = load.i64 notrap aligned readonly can_move region4 v0+104 +;; @00ad v27 = iconst.i32 49 +;; @00af call_indirect sig0, v32(v33, v0, v27) ; v27 = 49 +;; @00b1 trap user12 ;; ;; block2(v5: i32): -;; @00bc jump block1(v5) +;; @00b3 jump block1(v5) ;; ;; block1(v3: i32): -;; @00bc return v3 +;; @00b3 return v3 ;; } diff --git a/tests/disas/riscv64-component-builtins-asm.wat b/tests/disas/riscv64-component-builtins-asm.wat index 434980861b36..9a71f7ea3047 100644 --- a/tests/disas/riscv64-component-builtins-asm.wat +++ b/tests/disas/riscv64-component-builtins-asm.wat @@ -17,17 +17,16 @@ ;; sd s0, 0(sp) ;; mv s0, sp ;; addi sp, sp, -0x10 -;; sd s5, 8(sp) -;; sd s9, 0(sp) -;; mv s5, a1 -;; mv s9, a2 +;; sd s4, 8(sp) +;; sd s8, 0(sp) +;; mv s4, a1 +;; mv s8, a2 ;; mv a3, s0 ;; ld a1, 8(a1) ;; sd a3, 0x30(a1) ;; ld a2, 8(s0) ;; sd a2, 0x38(a1) ;; lw a1, 0x20(a0) -;; andi a1, a1, 1 ;; sext.w a1, a1 ;; bnez a1, 8 ;; .byte 0x00, 0x00, 0x00, 0x00 @@ -39,20 +38,20 @@ ;; srai a1, a1, 0x20 ;; slli a2, a4, 0x20 ;; srai a2, a2, 0x20 -;; mv a3, s9 +;; mv a3, s8 ;; slli a3, a3, 0x20 ;; srai a3, a3, 0x20 ;; jalr a5 ;; addi a1, zero, -1 ;; beq a0, a1, 0x20 -;; ld s5, 8(sp) -;; ld s9, 0(sp) +;; ld s4, 8(sp) +;; ld s8, 0(sp) ;; addi sp, sp, 0x10 ;; ld ra, 8(sp) ;; ld s0, 0(sp) ;; addi sp, sp, 0x10 ;; ret -;; mv a1, s5 +;; mv a1, s4 ;; ld a0, 0x10(a1) ;; ld a2, 0x148(a0) ;; mv a0, a1 diff --git a/tests/disas/riscv64-component-builtins.wat b/tests/disas/riscv64-component-builtins.wat index bee89c881388..46b0e1fff256 100644 --- a/tests/disas/riscv64-component-builtins.wat +++ b/tests/disas/riscv64-component-builtins.wat @@ -27,25 +27,23 @@ ;; v5 = get_return_address.i64 ;; store notrap aligned region2 v5, v3+56 ;; v6 = load.i32 notrap aligned region3 v0+32 -;; v7 = iconst.i32 1 -;; v8 = band v6, v7 ; v7 = 1 -;; trapz v8, user26 -;; v11 = load.i64 notrap aligned readonly region4 v0+8 -;; v12 = load.i64 notrap aligned readonly v11+16 -;; v9 = iconst.i32 0 -;; v13 = call_indirect sig0, v12(v0, v9, v9, v2) ; v9 = 0, v9 = 0 -;; v14 = iconst.i64 -1 -;; v15 = icmp ne v13, v14 ; v14 = -1 -;; brif v15, block2, block1 +;; trapz v6, user26 +;; v9 = load.i64 notrap aligned readonly region4 v0+8 +;; v10 = load.i64 notrap aligned readonly v9+16 +;; v7 = iconst.i32 0 +;; v11 = call_indirect sig0, v10(v0, v7, v7, v2) ; v7 = 0, v7 = 0 +;; v12 = iconst.i64 -1 +;; v13 = icmp ne v11, v12 ; v12 = -1 +;; brif v13, block2, block1 ;; ;; block1 cold: -;; v16 = load.i64 notrap aligned readonly can_move region5 v1+16 -;; v17 = load.i64 notrap aligned readonly can_move v16+328 -;; call_indirect sig1, v17(v1) +;; v14 = load.i64 notrap aligned readonly can_move region5 v1+16 +;; v15 = load.i64 notrap aligned readonly can_move v14+328 +;; call_indirect sig1, v15(v1) ;; trap user1 ;; ;; block2: -;; brif.i64 v13, block3, block4 +;; brif.i64 v11, block3, block4 ;; ;; block3: ;; jump block4