diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 105e313a6..f932534e7 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -447,7 +447,7 @@ jobs: - uses: ./.github/actions/install-rust - run: rustup component add clippy - - run: cargo clippy --workspace --all-targets + - run: cargo clippy --workspace --all-targets --features p3,component-model-async # Similar to `micro_checks` but where we need to install some more state # (e.g. Android NDK) and we haven't factored support for those things out into diff --git a/.gitignore b/.gitignore index 5777a294a..28a72405b 100644 --- a/.gitignore +++ b/.gitignore @@ -26,9 +26,7 @@ examples/.cache *.smt2 cranelift/isle/veri/veri_engine/test_output crates/explorer/node_modules -tests/all/pulley_provenance_test.cwasm -tests/all/pulley_provenance_test_component.cwasm -tests/all/pulley_provenance_test_async_component.cwasm +*.cwasm /artifacts testcase*.wat testcase*.wasm diff --git a/Cargo.lock b/Cargo.lock index f62977ed3..89e88edcf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4914,6 +4914,7 @@ dependencies = [ "anyhow", "cranelift-codegen", "gimli 0.32.0", + "log", "object 0.37.1", "target-lexicon", "wasmparser 0.236.0", diff --git a/cranelift/codegen/src/inline.rs b/cranelift/codegen/src/inline.rs index 1d3f21c9a..1f75378e1 100644 --- a/cranelift/codegen/src/inline.rs +++ b/cranelift/codegen/src/inline.rs @@ -445,7 +445,7 @@ fn inline_one( // terminator, so do a quick pass over the inlined blocks and remove any // empty blocks from the caller's layout. for block in entity_map.iter_inlined_blocks(func) { - if func.layout.first_inst(block).is_none() { + if func.layout.is_block_inserted(block) && func.layout.first_inst(block).is_none() { func.layout.remove_block(block); } } diff --git a/crates/cranelift/src/compiler.rs b/crates/cranelift/src/compiler.rs index c0434a271..afe17279b 100644 --- a/crates/cranelift/src/compiler.rs +++ b/crates/cranelift/src/compiler.rs @@ -30,10 +30,10 @@ use std::sync::{Arc, Mutex}; use wasmparser::{FuncValidatorAllocations, FunctionBody}; use wasmtime_environ::{ AddressMapSection, BuiltinFunctionIndex, CacheStore, CompileError, CompiledFunctionBody, - DefinedFuncIndex, FlagValue, FuncIndex, FunctionBodyData, FunctionLoc, HostCall, - InliningCompiler, ModuleTranslation, ModuleTypesBuilder, PtrSize, RelocationTarget, - StackMapSection, StaticModuleIndex, TrapEncodingBuilder, TrapSentinel, TripleExt, Tunables, - VMOffsets, WasmFuncType, WasmValType, + DefinedFuncIndex, FlagValue, FuncKey, FunctionBodyData, FunctionLoc, HostCall, + InliningCompiler, ModuleTranslation, ModuleTypesBuilder, PtrSize, StackMapSection, + StaticModuleIndex, TrapEncodingBuilder, TrapSentinel, TripleExt, Tunables, VMOffsets, + WasmFuncType, WasmValType, }; #[cfg(feature = "component-model")] @@ -176,12 +176,13 @@ impl Compiler { .params .insert(0, ir::AbiParam::new(self.isa.pointer_type())); let new_sig = builder.func.import_signature(new_signature); - let name = ir::ExternalName::User(builder.func.declare_imported_user_function( - ir::UserExternalName { - namespace: crate::NS_PULLEY_HOSTCALL, - index: hostcall.into().index(), - }, - )); + let key = FuncKey::PulleyHostCall(hostcall.into()); + let (namespace, index) = key.into_raw_parts(); + let name = ir::ExternalName::User( + builder + .func + .declare_imported_user_function(ir::UserExternalName { namespace, index }), + ); let func = builder.func.import_function(ir::ExtFuncData { name, signature: new_sig, @@ -198,6 +199,29 @@ impl Compiler { } } +fn box_dyn_any_compiled_function(f: CompiledFunction) -> Box { + let b = box_dyn_any(f); + debug_assert!(b.is::()); + b +} + +fn box_dyn_any_compiler_context(ctx: Option) -> Box { + let b = box_dyn_any(ctx); + debug_assert!(b.is::>()); + b +} + +fn box_dyn_any(x: impl Any + Send + Sync) -> Box { + log::trace!( + "making Box of {}", + std::any::type_name_of_val(&x) + ); + let b = Box::new(x); + let r: &(dyn Any + Sync + Send) = &*b; + log::trace!(" --> {r:#p}"); + b +} + impl wasmtime_environ::Compiler for Compiler { fn inlining_compiler(&self) -> Option<&dyn wasmtime_environ::InliningCompiler> { Some(self) @@ -206,14 +230,20 @@ impl wasmtime_environ::Compiler for Compiler { fn compile_function( &self, translation: &ModuleTranslation<'_>, - func_index: DefinedFuncIndex, + key: FuncKey, input: FunctionBodyData<'_>, types: &ModuleTypesBuilder, symbol: &str, ) -> Result { + log::trace!("compiling Wasm function: {key:?} = {symbol:?}"); + let isa = &*self.isa; let module = &translation.module; - let func_index = module.func_index(func_index); + + let (module_index, def_func_index) = key.unwrap_defined_wasm_function(); + debug_assert_eq!(translation.module_index, module_index); + + let func_index = module.func_index(def_func_index); let sig = translation.module.functions[func_index] .signature .unwrap_module_type_index(); @@ -223,10 +253,8 @@ impl wasmtime_environ::Compiler for Compiler { let context = &mut compiler.cx.codegen_context; context.func.signature = wasm_call_signature(isa, wasm_func_ty, &self.tunables); - context.func.name = UserFuncName::User(UserExternalName { - namespace: crate::NS_WASM_FUNC, - index: func_index.as_u32(), - }); + let (namespace, index) = key.into_raw_parts(); + context.func.name = UserFuncName::User(UserExternalName { namespace, index }); if self.tunables.generate_native_debuginfo { context.func.collect_debug_info(); @@ -311,7 +339,7 @@ impl wasmtime_environ::Compiler for Compiler { log::trace!("`{symbol}` timing info\n{timing}"); Ok(CompiledFunctionBody { - code: Box::new(Some(compiler.cx)), + code: box_dyn_any_compiler_context(Some(compiler.cx)), needs_gc_heap: func_env.needs_gc_heap(), }) } @@ -320,9 +348,14 @@ impl wasmtime_environ::Compiler for Compiler { &self, translation: &ModuleTranslation<'_>, types: &ModuleTypesBuilder, - def_func_index: DefinedFuncIndex, - _symbol: &str, + key: FuncKey, + symbol: &str, ) -> Result { + log::trace!("compiling array-to-wasm trampoline: {key:?} = {symbol:?}"); + + let (module_index, def_func_index) = key.unwrap_array_to_wasm_trampoline(); + debug_assert_eq!(translation.module_index, module_index); + let func_index = translation.module.func_index(def_func_index); let sig = translation.module.functions[func_index] .signature @@ -369,7 +402,8 @@ impl wasmtime_environ::Compiler for Compiler { ); // Then call the Wasm function with those arguments. - let call = declare_and_call(&mut builder, wasm_call_sig, func_index.as_u32(), &args); + let callee_key = FuncKey::DefinedWasmFunction(module_index, def_func_index); + let call = declare_and_call(&mut builder, wasm_call_sig, callee_key, &args); let results = builder.func.dfg.inst_results(call).to_vec(); // Then store the results back into the array. @@ -390,7 +424,7 @@ impl wasmtime_environ::Compiler for Compiler { builder.finalize(); Ok(CompiledFunctionBody { - code: Box::new(Some(compiler.cx)), + code: box_dyn_any_compiler_context(Some(compiler.cx)), needs_gc_heap: false, }) } @@ -398,8 +432,11 @@ impl wasmtime_environ::Compiler for Compiler { fn compile_wasm_to_array_trampoline( &self, wasm_func_ty: &WasmFuncType, - _symbol: &str, + key: FuncKey, + symbol: &str, ) -> Result { + log::trace!("compiling wasm-to-array trampoline: {key:?} = {symbol:?}"); + let isa = &*self.isa; let pointer_type = isa.pointer_type(); let wasm_call_sig = wasm_call_signature(isa, wasm_func_ty, &self.tunables); @@ -464,7 +501,7 @@ impl wasmtime_environ::Compiler for Compiler { builder.finalize(); Ok(CompiledFunctionBody { - code: Box::new(Some(compiler.cx)), + code: box_dyn_any_compiler_context(Some(compiler.cx)), needs_gc_heap: false, }) } @@ -473,8 +510,13 @@ impl wasmtime_environ::Compiler for Compiler { &self, obj: &mut Object<'static>, funcs: &[(String, Box)], - resolve_reloc: &dyn Fn(usize, RelocationTarget) -> usize, + resolve_reloc: &dyn Fn(usize, FuncKey) -> usize, ) -> Result> { + log::trace!( + "appending functions to object file: {:#?}", + funcs.iter().map(|(sym, _)| sym).collect::>() + ); + let mut builder = ModuleTextBuilder::new(obj, self, self.isa.text_section_builder(funcs.len())); if self.linkopts.force_jump_veneers { @@ -486,24 +528,32 @@ impl wasmtime_environ::Compiler for Compiler { let mut ret = Vec::with_capacity(funcs.len()); for (i, (sym, func)) in funcs.iter().enumerate() { + debug_assert!(!func.is::>()); + debug_assert!(func.is::()); let func = func.downcast_ref::().unwrap(); - let (sym, range) = builder.append_func(&sym, func, |idx| resolve_reloc(i, idx)); + + let (sym_id, range) = builder.append_func(&sym, func, |idx| resolve_reloc(i, idx)); + log::trace!("symbol id {sym_id:?} = {sym:?}"); + if self.tunables.generate_address_map { let addr = func.address_map(); addrs.push(range.clone(), &addr.instructions); } + clif_to_env_stack_maps( &mut stack_maps, range.clone(), func.buffer.user_stack_maps(), ); + traps.push(range.clone(), &func.traps().collect::>()); builder.append_padding(self.linkopts.padding_between_functions); + let info = FunctionLoc { start: u32::try_from(range.start).unwrap(), length: u32::try_from(range.end - range.start).unwrap(), }; - ret.push((sym, info)); + ret.push((sym_id, info)); } builder.finish(); @@ -549,13 +599,19 @@ impl wasmtime_environ::Compiler for Compiler { dwarf_package_bytes: Option<&'a [u8]>, tunables: &'a Tunables, ) -> Result<()> { + log::trace!("appending DWARF debug info"); + let get_func = move |m, f| { let (sym, any) = get_func(m, f); + log::trace!("get_func({m:?}, {f:?}) -> ({sym:?}, {any:#p})"); + debug_assert!(!any.is::>()); + debug_assert!(any.is::()); ( sym, any.downcast_ref::().unwrap().metadata(), ) }; + let mut compilation = crate::debug::Compilation::new( &*self.isa, translations, @@ -613,15 +669,18 @@ impl wasmtime_environ::Compiler for Compiler { fn compile_wasm_to_builtin( &self, - index: BuiltinFunctionIndex, - _symbol: &str, + key: FuncKey, + symbol: &str, ) -> Result { + log::trace!("compiling wasm-to-builtin trampoline: {key:?} = {symbol:?}"); + let isa = &*self.isa; let ptr_size = isa.pointer_bytes(); let pointer_type = isa.pointer_type(); let sigs = BuiltinFunctionSignatures::new(self); - let wasm_sig = sigs.wasm_signature(index); - let host_sig = sigs.host_signature(index); + let builtin_func_index = key.unwrap_wasm_to_builtin_trampoline(); + let wasm_sig = sigs.wasm_signature(builtin_func_index); + let host_sig = sigs.host_signature(builtin_func_index); let mut compiler = self.function_compiler(); let func = ir::Function::with_name_signature(Default::default(), wasm_sig.clone()); @@ -643,7 +702,7 @@ impl wasmtime_environ::Compiler for Compiler { // Now it's time to delegate to the actual builtin. Forward all our own // arguments to the libcall itself. let args = builder.block_params(block0).to_vec(); - let call = self.call_builtin(&mut builder, vmctx, &args, index, host_sig); + let call = self.call_builtin(&mut builder, vmctx, &args, builtin_func_index, host_sig); let results = builder.func.dfg.inst_results(call).to_vec(); // Libcalls do not explicitly `longjmp` for example but instead return a @@ -652,7 +711,7 @@ impl wasmtime_environ::Compiler for Compiler { // value and raise a trap as appropriate. With the `results` above check // what `index` is and for each libcall that has a trapping return value // process it here. - match index.trap_sentinel() { + match builtin_func_index.trap_sentinel() { Some(TrapSentinel::Falsy) => { self.raise_if_host_trapped(&mut builder, vmctx, results[0]); } @@ -685,7 +744,7 @@ impl wasmtime_environ::Compiler for Compiler { builder.finalize(); Ok(CompiledFunctionBody { - code: Box::new(Some(compiler.cx)), + code: box_dyn_any_compiler_context(Some(compiler.cx)), needs_gc_heap: false, }) } @@ -693,7 +752,9 @@ impl wasmtime_environ::Compiler for Compiler { fn compiled_function_relocation_targets<'a>( &'a self, func: &'a dyn Any, - ) -> Box + 'a> { + ) -> Box + 'a> { + debug_assert!(!func.is::>()); + debug_assert!(func.is::()); let func = func.downcast_ref::().unwrap(); Box::new(func.relocations().map(|r| r.reloc_target)) } @@ -703,8 +764,10 @@ impl InliningCompiler for Compiler { fn calls( &self, func_body: &CompiledFunctionBody, - calls: &mut wasmtime_environ::prelude::IndexSet, + calls: &mut wasmtime_environ::prelude::IndexSet, ) -> Result<()> { + debug_assert!(!func_body.code.is::()); + debug_assert!(func_body.code.is::>()); let cx = func_body .code .downcast_ref::>() @@ -716,13 +779,15 @@ impl InliningCompiler for Compiler { func.params .user_named_funcs() .values() - .filter(|name| name.namespace == crate::NS_WASM_FUNC) - .map(|name| FuncIndex::from_u32(name.index)), + .map(|name| FuncKey::from_raw_parts(name.namespace, name.index)) + .filter(|key| matches!(key, FuncKey::DefinedWasmFunction(_, _))), ); Ok(()) } fn size(&self, func_body: &CompiledFunctionBody) -> u32 { + debug_assert!(!func_body.code.is::()); + debug_assert!(func_body.code.is::>()); let cx = func_body .code .downcast_ref::>() @@ -737,8 +802,10 @@ impl InliningCompiler for Compiler { fn inline<'a>( &self, func_body: &mut CompiledFunctionBody, - get_callee: &'a mut dyn FnMut(FuncIndex) -> Option<&'a CompiledFunctionBody>, + get_callee: &'a mut dyn FnMut(FuncKey) -> Option<&'a CompiledFunctionBody>, ) -> Result<()> { + debug_assert!(!func_body.code.is::()); + debug_assert!(func_body.code.is::>()); let code = func_body .code .downcast_mut::>() @@ -748,7 +815,7 @@ impl InliningCompiler for Compiler { cx.codegen_context.inline(Inliner(get_callee))?; return Ok(()); - struct Inliner<'a>(&'a mut dyn FnMut(FuncIndex) -> Option<&'a CompiledFunctionBody>); + struct Inliner<'a>(&'a mut dyn FnMut(FuncKey) -> Option<&'a CompiledFunctionBody>); impl cranelift_codegen::inline::Inline for Inliner<'_> { fn inline( @@ -767,22 +834,23 @@ impl InliningCompiler for Compiler { | ir::ExternalName::KnownSymbol(_) => return InlineCommand::KeepCall, }; let callee = &caller.params.user_named_funcs()[callee]; - let callee = if callee.namespace == crate::NS_WASM_FUNC { - FuncIndex::from_u32(callee.index) - } else { - return InlineCommand::KeepCall; - }; - match (self.0)(callee) { - None => InlineCommand::KeepCall, - Some(func_body) => { - let cx = func_body - .code - .downcast_ref::>() - .unwrap(); - InlineCommand::Inline(Cow::Borrowed( - &cx.as_ref().unwrap().codegen_context.func, - )) - } + let callee = FuncKey::from_raw_parts(callee.namespace, callee.index); + match callee { + FuncKey::DefinedWasmFunction(_, _) => match (self.0)(callee) { + None => InlineCommand::KeepCall, + Some(func_body) => { + debug_assert!(!func_body.code.is::()); + debug_assert!(func_body.code.is::>()); + let cx = func_body + .code + .downcast_ref::>() + .unwrap(); + InlineCommand::Inline(Cow::Borrowed( + &cx.as_ref().unwrap().codegen_context.func, + )) + } + }, + _ => InlineCommand::KeepCall, } } } @@ -794,6 +862,9 @@ impl InliningCompiler for Compiler { input: Option>, symbol: &str, ) -> Result<()> { + log::trace!("finish compiling {symbol:?}"); + debug_assert!(!func_body.code.is::()); + debug_assert!(func_body.code.is::>()); let cx = func_body .code .downcast_mut::>() @@ -818,7 +889,7 @@ impl InliningCompiler for Compiler { log::debug!("`{symbol}` compiled in {:?}", timing.total()); log::trace!("`{symbol}` timing info\n{timing}"); - func_body.code = Box::new(compiled_func); + func_body.code = box_dyn_any_compiled_function(compiled_func); Ok(()) } } @@ -1256,15 +1327,15 @@ fn clif_to_env_stack_maps( fn declare_and_call( builder: &mut FunctionBuilder, signature: ir::Signature, - func_index: u32, + callee_key: FuncKey, args: &[ir::Value], ) -> ir::Inst { - let name = ir::ExternalName::User(builder.func.declare_imported_user_function( - ir::UserExternalName { - namespace: crate::NS_WASM_FUNC, - index: func_index, - }, - )); + let (namespace, index) = callee_key.into_raw_parts(); + let name = ir::ExternalName::User( + builder + .func + .declare_imported_user_function(ir::UserExternalName { namespace, index }), + ); let signature = builder.func.import_signature(signature); let callee = builder.func.dfg.ext_funcs.push(ir::ExtFuncData { name, diff --git a/crates/cranelift/src/compiler/component.rs b/crates/cranelift/src/compiler/component.rs index b60b5a2a9..1fee2475a 100644 --- a/crates/cranelift/src/compiler/component.rs +++ b/crates/cranelift/src/compiler/component.rs @@ -9,12 +9,12 @@ use cranelift_codegen::ir::condcodes::IntCC; use cranelift_codegen::ir::{self, InstBuilder, MemFlags, Value}; use cranelift_codegen::isa::{CallConv, TargetIsa}; use cranelift_frontend::FunctionBuilder; -use wasmtime_environ::fact::PREPARE_CALL_FIXED_PARAMS; use wasmtime_environ::{CompiledFunctionBody, component::*}; use wasmtime_environ::{ EntityRef, HostCall, ModuleInternedTypeIndex, PtrSize, TrapSentinel, Tunables, WasmFuncType, WasmValType, }; +use wasmtime_environ::{FuncKey, fact::PREPARE_CALL_FIXED_PARAMS}; struct TrampolineCompiler<'a> { compiler: &'a Compiler, @@ -1281,7 +1281,7 @@ impl ComponentCompiler for Compiler { &self, component: &ComponentTranslation, types: &ComponentTypesBuilder, - index: TrampolineIndex, + key: FuncKey, tunables: &Tunables, _symbol: &str, ) -> Result> { @@ -1292,7 +1292,7 @@ impl ComponentCompiler for Compiler { &mut compiler, &component.component, types, - index, + key.unwrap_component_trampoline(), abi, tunables, ); @@ -1325,12 +1325,12 @@ impl ComponentCompiler for Compiler { ); } - c.translate(&component.trampolines[index]); + c.translate(&component.trampolines[key.unwrap_component_trampoline()]); c.builder.finalize(); compiler.cx.abi = Some(abi); Ok(CompiledFunctionBody { - code: Box::new(Some(compiler.cx)), + code: super::box_dyn_any_compiler_context(Some(compiler.cx)), needs_gc_heap: false, }) }; diff --git a/crates/cranelift/src/debug/transform/address_transform.rs b/crates/cranelift/src/debug/transform/address_transform.rs index 9d84b4ce2..7de691c7f 100644 --- a/crates/cranelift/src/debug/transform/address_transform.rs +++ b/crates/cranelift/src/debug/transform/address_transform.rs @@ -498,8 +498,10 @@ impl AddressTransform { >, wasm_file: wasmtime_environ::WasmFileInfo, ) -> Self { + use cranelift_entity::EntityRef; + let mut translations = wasmtime_environ::PrimaryMap::new(); - let mut translation = wasmtime_environ::ModuleTranslation::default(); + let mut translation = wasmtime_environ::ModuleTranslation::new(StaticModuleIndex::new(0)); translation.debuginfo.wasm_file = wasm_file; translation .module diff --git a/crates/cranelift/src/debug/transform/mod.rs b/crates/cranelift/src/debug/transform/mod.rs index 4eb20832d..2cf171bb8 100644 --- a/crates/cranelift/src/debug/transform/mod.rs +++ b/crates/cranelift/src/debug/transform/mod.rs @@ -121,16 +121,20 @@ fn read_dwarf_package_from_bytes<'data>( let mut validator = wasmparser::Validator::new(); let parser = wasmparser::Parser::new(0); let mut types = wasmtime_environ::ModuleTypesBuilder::new(&validator); - let translation = - match wasmtime_environ::ModuleEnvironment::new(tunables, &mut validator, &mut types) - .translate(parser, dwp_bytes) - { - Ok(translation) => translation, - Err(e) => { - log::warn!("failed to parse wasm dwarf package: {e:?}"); - return None; - } - }; + let translation = match wasmtime_environ::ModuleEnvironment::new( + tunables, + &mut validator, + &mut types, + StaticModuleIndex::from_u32(0), + ) + .translate(parser, dwp_bytes) + { + Ok(translation) => translation, + Err(e) => { + log::warn!("failed to parse wasm dwarf package: {e:?}"); + return None; + } + }; match load_dwp(translation, buffer) { Ok(package) => Some(package), diff --git a/crates/cranelift/src/func_environ.rs b/crates/cranelift/src/func_environ.rs index 5586da114..e0ed28ba1 100644 --- a/crates/cranelift/src/func_environ.rs +++ b/crates/cranelift/src/func_environ.rs @@ -23,10 +23,10 @@ use std::mem; use wasmparser::{Operator, WasmFeatures}; use wasmtime_environ::{ BuiltinFunctionIndex, DataIndex, DefinedFuncIndex, ElemIndex, EngineOrModuleTypeIndex, - FuncIndex, GlobalIndex, IndexType, Memory, MemoryIndex, Module, ModuleInternedTypeIndex, - ModuleTranslation, ModuleTypesBuilder, PtrSize, Table, TableIndex, TripleExt, Tunables, - TypeConvert, TypeIndex, VMOffsets, WasmCompositeInnerType, WasmFuncType, WasmHeapTopType, - WasmHeapType, WasmRefType, WasmResult, WasmValType, + FuncIndex, FuncKey, GlobalIndex, IndexType, Memory, MemoryIndex, Module, + ModuleInternedTypeIndex, ModuleTranslation, ModuleTypesBuilder, PtrSize, Table, TableIndex, + TripleExt, Tunables, TypeConvert, TypeIndex, VMOffsets, WasmCompositeInnerType, WasmFuncType, + WasmHeapTopType, WasmHeapType, WasmRefType, WasmResult, WasmValType, }; use wasmtime_environ::{FUNCREF_INIT_BIT, FUNCREF_MASK}; use wasmtime_math::f64_cvt_to_int_bounds; @@ -53,17 +53,17 @@ impl BuiltinFunctions { } } - fn load_builtin(&mut self, func: &mut Function, index: BuiltinFunctionIndex) -> ir::FuncRef { - let cache = &mut self.builtins[index.index() as usize]; + fn load_builtin(&mut self, func: &mut Function, builtin: BuiltinFunctionIndex) -> ir::FuncRef { + let cache = &mut self.builtins[builtin.index() as usize]; if let Some(f) = cache { return *f; } - let signature = func.import_signature(self.types.wasm_signature(index)); - let name = - ir::ExternalName::User(func.declare_imported_user_function(ir::UserExternalName { - namespace: crate::NS_WASMTIME_BUILTIN, - index: index.index(), - })); + let signature = func.import_signature(self.types.wasm_signature(builtin)); + let key = FuncKey::WasmToBuiltinTrampoline(builtin); + let (namespace, index) = key.into_raw_parts(); + let name = ir::ExternalName::User( + func.declare_imported_user_function(ir::UserExternalName { namespace, index }), + ); let f = func.import_function(ir::ExtFuncData { name, signature, @@ -1265,15 +1265,18 @@ impl FuncEnvironment<'_> { def_func_index: DefinedFuncIndex, ) -> ir::FuncRef { let func_index = self.module.func_index(def_func_index); + let ty = self.module.functions[func_index] .signature .unwrap_module_type_index(); let signature = self.get_or_create_interned_sig_ref(func, ty); - let name = - ir::ExternalName::User(func.declare_imported_user_function(ir::UserExternalName { - namespace: crate::NS_WASM_FUNC, - index: func_index.as_u32(), - })); + + let key = FuncKey::DefinedWasmFunction(self.translation.module_index, def_func_index); + let (namespace, index) = key.into_raw_parts(); + let name = ir::ExternalName::User( + func.declare_imported_user_function(ir::UserExternalName { namespace, index }), + ); + func.import_function(ir::ExtFuncData { name, signature, @@ -1288,15 +1291,20 @@ impl FuncEnvironment<'_> { ) -> ir::FuncRef { assert!(self.module.is_imported_function(func_index)); assert!(self.translation.known_imported_functions[func_index].is_some()); + let ty = self.module.functions[func_index] .signature .unwrap_module_type_index(); let signature = self.get_or_create_interned_sig_ref(func, ty); - let name = - ir::ExternalName::User(func.declare_imported_user_function(ir::UserExternalName { - namespace: crate::NS_WASM_FUNC, - index: func_index.as_u32(), - })); + + let (module, def_func_index) = + self.translation.known_imported_functions[func_index].unwrap(); + let key = FuncKey::DefinedWasmFunction(module, def_func_index); + let (namespace, index) = key.into_raw_parts(); + let name = ir::ExternalName::User( + func.declare_imported_user_function(ir::UserExternalName { namespace, index }), + ); + func.import_function(ir::ExtFuncData { name, signature, diff --git a/crates/cranelift/src/lib.rs b/crates/cranelift/src/lib.rs index 93748ad40..b25fc8921 100644 --- a/crates/cranelift/src/lib.rs +++ b/crates/cranelift/src/lib.rs @@ -25,8 +25,8 @@ use cranelift_entity::PrimaryMap; use target_lexicon::Architecture; use wasmtime_environ::{ - BuiltinFunctionIndex, FlagValue, FuncIndex, RelocationTarget, Trap, TrapInformation, Tunables, - WasmFuncType, WasmHeapTopType, WasmHeapType, WasmValType, + BuiltinFunctionIndex, FlagValue, FuncKey, Trap, TrapInformation, Tunables, WasmFuncType, + WasmHeapTopType, WasmHeapType, WasmValType, }; pub use builder::builder; @@ -223,29 +223,13 @@ fn reference_type(wasm_ht: WasmHeapType, pointer_type: ir::Type) -> ir::Type { // List of namespaces which are processed in `mach_reloc_to_reloc` below. -/// Namespace corresponding to wasm functions, the index is the index of the -/// defined function that's being referenced. -pub const NS_WASM_FUNC: u32 = 0; - -/// Namespace for builtin function trampolines. The index is the index of the -/// builtin that's being referenced. These trampolines invoke the real host -/// function through an indirect function call loaded by the `VMContext`. -pub const NS_WASMTIME_BUILTIN: u32 = 1; - -/// Namespace used to when a call from Pulley to the host is being made. This is -/// used with a `colocated: false` name to trigger codegen for a special opcode -/// for pulley-to-host communication. The index of the functions used in this -/// namespace correspond to the function signature of `for_each_host_signature!` -/// in the pulley_interpreter crate. -pub const NS_PULLEY_HOSTCALL: u32 = 2; - /// A record of a relocation to perform. #[derive(Debug, Clone, PartialEq, Eq)] pub struct Relocation { /// The relocation code. pub reloc: binemit::Reloc, /// Relocation target. - pub reloc_target: RelocationTarget, + pub reloc_target: FuncKey, /// The offset where to apply the relocation. pub offset: binemit::CodeOffset, /// The addend to add to the relocation value. @@ -312,14 +296,7 @@ fn mach_reloc_to_reloc( let reloc_target = match *target { FinalizedRelocTarget::ExternalName(ExternalName::User(user_func_ref)) => { let name = &name_map[user_func_ref]; - match name.namespace { - NS_WASM_FUNC => RelocationTarget::Wasm(FuncIndex::from_u32(name.index)), - NS_WASMTIME_BUILTIN => { - RelocationTarget::Builtin(BuiltinFunctionIndex::from_u32(name.index)) - } - NS_PULLEY_HOSTCALL => RelocationTarget::PulleyHostcall(name.index), - _ => panic!("unknown namespace {}", name.namespace), - } + FuncKey::from_raw_parts(name.namespace, name.index) } FinalizedRelocTarget::ExternalName(ExternalName::LibCall(libcall)) => { // We should have avoided any code that needs this style of libcalls diff --git a/crates/cranelift/src/obj.rs b/crates/cranelift/src/obj.rs index db7667315..cd3142abe 100644 --- a/crates/cranelift/src/obj.rs +++ b/crates/cranelift/src/obj.rs @@ -13,7 +13,7 @@ //! function body, the imported wasm function do not. The trampolines symbol //! names have format "_trampoline_N", where N is `SignatureIndex`. -use crate::{CompiledFunction, RelocationTarget}; +use crate::CompiledFunction; use anyhow::Result; use cranelift_codegen::TextSectionBuilder; use cranelift_codegen::isa::unwind::{UnwindInfo, systemv}; @@ -23,8 +23,8 @@ use gimli::write::{Address, EhFrame, EndianVec, FrameTable, Writer}; use object::write::{Object, SectionId, StandardSegment, Symbol, SymbolId, SymbolSection}; use object::{Architecture, SectionFlags, SectionKind, SymbolFlags, SymbolKind, SymbolScope}; use std::ops::Range; -use wasmtime_environ::obj; use wasmtime_environ::{Compiler, TripleExt}; +use wasmtime_environ::{FuncKey, obj}; const TEXT_SECTION_NAME: &[u8] = b".text"; @@ -120,7 +120,7 @@ impl<'a> ModuleTextBuilder<'a> { &mut self, name: &str, compiled_func: &'a CompiledFunction, - resolve_reloc_target: impl Fn(wasmtime_environ::RelocationTarget) -> usize, + resolve_reloc_target: impl Fn(wasmtime_environ::FuncKey) -> usize, ) -> (SymbolId, Range) { let body = compiled_func.buffer.data(); let alignment = compiled_func.alignment; @@ -146,65 +146,49 @@ impl<'a> ModuleTextBuilder<'a> { for r in compiled_func.relocations() { let reloc_offset = off + u64::from(r.offset); - match r.reloc_target { - // Relocations against user-defined functions means that this is - // a relocation against a module-local function, typically a - // call between functions. The `text` field is given priority to - // resolve this relocation before we actually emit an object - // file, but if it can't handle it then we pass through the - // relocation. - RelocationTarget::Wasm(_) | RelocationTarget::Builtin(_) => { - let target = resolve_reloc_target(r.reloc_target); - if self - .text - .resolve_reloc(reloc_offset, r.reloc, r.addend, target) - { - continue; - } - - // At this time it's expected that all relocations are - // handled by `text.resolve_reloc`, and anything that isn't - // handled is a bug in `text.resolve_reloc` or something - // transitively there. If truly necessary, though, then this - // loop could also be updated to forward the relocation to - // the final object file as well. - panic!( - "unresolved relocation could not be processed against \ - {:?}: {r:?}", - r.reloc_target, - ); - } - // This relocation is used to fill in which hostcall id is - // desired within the `call_indirect_host` opcode of Pulley - // itself. The relocation target is the start of the instruction - // and the goal is to insert the static signature number, `n`, - // into the instruction. - // - // At this time the instruction looks like: - // - // +------+------+------+------+ - // | OP | OP_EXTENDED | N | - // +------+------+------+------+ - // - // This 4-byte encoding has `OP` indicating this is an "extended - // opcode" where `OP_EXTENDED` is a 16-bit extended opcode. - // The `N` byte is the index of the signature being called and - // is what's b eing filled in. - // - // See the `test_call_indirect_host_width` in - // `pulley/tests/all.rs` for this guarantee as well. - RelocationTarget::PulleyHostcall(n) => { - #[cfg(feature = "pulley")] - { - use pulley_interpreter::encode::Encode; - assert_eq!(pulley_interpreter::CallIndirectHost::WIDTH, 4); - } - let byte = u8::try_from(n).unwrap(); - self.text.write(reloc_offset + 3, &[byte]); + // This relocation is used to fill in which hostcall id is + // desired within the `call_indirect_host` opcode of Pulley + // itself. The relocation target is the start of the instruction + // and the goal is to insert the static signature number, `n`, + // into the instruction. + // + // At this time the instruction looks like: + // + // +------+------+------+------+ + // | OP | OP_EXTENDED | N | + // +------+------+------+------+ + // + // This 4-byte encoding has `OP` indicating this is an "extended + // opcode" where `OP_EXTENDED` is a 16-bit extended opcode. + // The `N` byte is the index of the signature being called and + // is what's b eing filled in. + // + // See the `test_call_indirect_host_width` in + // `pulley/tests/all.rs` for this guarantee as well. + if let FuncKey::PulleyHostCall(host_call) = r.reloc_target { + #[cfg(feature = "pulley")] + { + use pulley_interpreter::encode::Encode; + assert_eq!(pulley_interpreter::CallIndirectHost::WIDTH, 4); } - }; + let n = host_call.index(); + let byte = u8::try_from(n).unwrap(); + self.text.write(reloc_offset + 3, &[byte]); + continue; + } + + let target = resolve_reloc_target(r.reloc_target); + if self + .text + .resolve_reloc(reloc_offset, r.reloc, r.addend, target) + { + continue; + } + + panic!("failed to resolve relocation: {r:?} -> {target}"); } + (symbol_id, off..off + body_len) } diff --git a/crates/environ/src/compile/key.rs b/crates/environ/src/compile/key.rs new file mode 100644 index 000000000..140bd08c7 --- /dev/null +++ b/crates/environ/src/compile/key.rs @@ -0,0 +1,221 @@ +//! Keys for identifying functions during compilation, in call graphs, and when +//! resolving relocations. + +#[cfg(feature = "component-model")] +use crate::component; +use crate::{ + BuiltinFunctionIndex, DefinedFuncIndex, HostCall, ModuleInternedTypeIndex, StaticModuleIndex, +}; + +/// A sortable, comparable function key for compilation output, call graph +/// edges, and relocations. +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum FuncKey { + /// A Wasm-defined function. + DefinedWasmFunction(StaticModuleIndex, DefinedFuncIndex), + + /// A trampoline from an array-caller to the given Wasm-callee. + ArrayToWasmTrampoline(StaticModuleIndex, DefinedFuncIndex), + + /// A trampoline from a Wasm-caller to an array-callee of the given type. + WasmToArrayTrampoline(ModuleInternedTypeIndex), + + /// A trampoline from a Wasm-caller to the given builtin. + WasmToBuiltinTrampoline(BuiltinFunctionIndex), + + /// A Pulley-specific host call. + PulleyHostCall(HostCall), + + /// A Wasm-caller to component builtin trampoline. + #[cfg(feature = "component-model")] + ComponentTrampoline(component::TrampolineIndex), + + /// A Wasm-caller to array-callee `resource.drop` trampoline. + #[cfg(feature = "component-model")] + ResourceDropTrampoline, +} + +impl FuncKey { + const KIND_BITS: u32 = 3; + const KIND_OFFSET: u32 = 32 - Self::KIND_BITS; + const KIND_MASK: u32 = ((1 << Self::KIND_BITS) - 1) << Self::KIND_OFFSET; + const MODULE_MASK: u32 = !Self::KIND_MASK; + + const fn new_kind(kind: u32) -> u32 { + assert!(kind < (1 << Self::KIND_BITS)); + kind << Self::KIND_OFFSET + } + + const DEFINED_WASM_FUNCTION_KIND: u32 = Self::new_kind(0); + const ARRAY_TO_WASM_TRAMPOLINE_KIND: u32 = Self::new_kind(1); + const WASM_TO_ARRAY_TRAMPOLINE_KIND: u32 = Self::new_kind(2); + const WASM_TO_BUILTIN_TRAMPOLINE_KIND: u32 = Self::new_kind(3); + const PULLEY_HOST_CALL_KIND: u32 = Self::new_kind(4); + + #[cfg(feature = "component-model")] + const COMPONENT_TRAMPOLINE_KIND: u32 = Self::new_kind(5); + #[cfg(feature = "component-model")] + const RESOURCE_DROP_TRAMPOLINE_KIND: u32 = Self::new_kind(6); + + /// Get the raw, underlying representation of this compilation key. + /// + /// The resulting values should only be used for (eventually) calling + /// `CompileKey::from_raw_parts`. + // + // NB: We use two `u32`s to exactly match + // `cranelift_codegen::ir::UserExternalName` and ensure that we can map + // one-to-one between that and `FuncKey`. + pub fn into_raw_parts(self) -> (u32, u32) { + match self { + FuncKey::DefinedWasmFunction(module, def_func) => { + assert_eq!(module.as_u32() & Self::KIND_MASK, 0); + let namespace = Self::DEFINED_WASM_FUNCTION_KIND | module.as_u32(); + let index = def_func.as_u32(); + (namespace, index) + } + FuncKey::ArrayToWasmTrampoline(module, def_func) => { + assert_eq!(module.as_u32() & Self::KIND_MASK, 0); + let namespace = Self::ARRAY_TO_WASM_TRAMPOLINE_KIND | module.as_u32(); + let index = def_func.as_u32(); + (namespace, index) + } + FuncKey::WasmToArrayTrampoline(ty) => { + let namespace = Self::WASM_TO_ARRAY_TRAMPOLINE_KIND; + let index = ty.as_u32(); + (namespace, index) + } + FuncKey::WasmToBuiltinTrampoline(builtin) => { + let namespace = Self::WASM_TO_BUILTIN_TRAMPOLINE_KIND; + let index = builtin.index(); + (namespace, index) + } + FuncKey::PulleyHostCall(host_call) => { + let namespace = Self::PULLEY_HOST_CALL_KIND; + let index = host_call.index(); + (namespace, index) + } + + #[cfg(feature = "component-model")] + FuncKey::ComponentTrampoline(trampoline) => { + let namespace = Self::COMPONENT_TRAMPOLINE_KIND; + let index = trampoline.as_u32(); + (namespace, index) + } + #[cfg(feature = "component-model")] + FuncKey::ResourceDropTrampoline => { + let namespace = Self::RESOURCE_DROP_TRAMPOLINE_KIND; + let index = 0; + (namespace, index) + } + } + } + + /// Create a compilation key from its raw, underlying representation. + /// + /// Should only be given the results of a previous call to + /// `CompileKey::into_raw_parts`. + pub fn from_raw_parts(a: u32, b: u32) -> Self { + match a & Self::KIND_MASK { + Self::DEFINED_WASM_FUNCTION_KIND => { + let module = StaticModuleIndex::from_u32(a & Self::MODULE_MASK); + let def_func = DefinedFuncIndex::from_u32(b); + Self::DefinedWasmFunction(module, def_func) + } + Self::ARRAY_TO_WASM_TRAMPOLINE_KIND => { + let module = StaticModuleIndex::from_u32(a & Self::MODULE_MASK); + let def_func = DefinedFuncIndex::from_u32(b); + Self::ArrayToWasmTrampoline(module, def_func) + } + Self::WASM_TO_ARRAY_TRAMPOLINE_KIND => { + assert_eq!(a & Self::MODULE_MASK, 0); + let ty = ModuleInternedTypeIndex::from_u32(b); + Self::WasmToArrayTrampoline(ty) + } + Self::WASM_TO_BUILTIN_TRAMPOLINE_KIND => { + assert_eq!(a & Self::MODULE_MASK, 0); + let builtin = BuiltinFunctionIndex::from_u32(b); + Self::WasmToBuiltinTrampoline(builtin) + } + Self::PULLEY_HOST_CALL_KIND => { + assert_eq!(a & Self::MODULE_MASK, 0); + let host_call = HostCall::from_index(b); + Self::PulleyHostCall(host_call) + } + + #[cfg(feature = "component-model")] + Self::COMPONENT_TRAMPOLINE_KIND => { + assert_eq!(a & Self::MODULE_MASK, 0); + let trampoline = component::TrampolineIndex::from_u32(b); + Self::ComponentTrampoline(trampoline) + } + #[cfg(feature = "component-model")] + Self::RESOURCE_DROP_TRAMPOLINE_KIND => { + assert_eq!(a & Self::MODULE_MASK, 0); + assert_eq!(b, 0); + Self::ResourceDropTrampoline + } + + k => panic!( + "bad raw parts given to `FuncKey::from_raw_parts` call: ({a}, {b}), kind would be {k}" + ), + } + } + + /// Unwrap a `FuncKey::DefinedWasmFunction` or else panic. + pub fn unwrap_defined_wasm_function(self) -> (StaticModuleIndex, DefinedFuncIndex) { + match self { + Self::DefinedWasmFunction(module, def_func) => (module, def_func), + _ => panic!("`FuncKey::unwrap_defined_wasm_function` called on {self:?}"), + } + } + + /// Unwrap a `FuncKey::ArrayToWasmTrampoline` or else panic. + pub fn unwrap_array_to_wasm_trampoline(self) -> (StaticModuleIndex, DefinedFuncIndex) { + match self { + Self::ArrayToWasmTrampoline(module, def_func) => (module, def_func), + _ => panic!("`FuncKey::unwrap_array_to_wasm_trampoline` called on {self:?}"), + } + } + + /// Unwrap a `FuncKey::WasmToArrayTrampoline` or else panic. + pub fn unwrap_wasm_to_array_trampoline(self) -> ModuleInternedTypeIndex { + match self { + Self::WasmToArrayTrampoline(ty) => ty, + _ => panic!("`FuncKey::unwrap_wasm_to_array_trampoline` called on {self:?}"), + } + } + + /// Unwrap a `FuncKey::WasmToBuiltinTrampoline` or else panic. + pub fn unwrap_wasm_to_builtin_trampoline(self) -> BuiltinFunctionIndex { + match self { + Self::WasmToBuiltinTrampoline(builtin) => builtin, + _ => panic!("`FuncKey::unwrap_wasm_to_builtin_trampoline` called on {self:?}"), + } + } + + /// Unwrap a `FuncKey::PulleyHostCall` or else panic. + pub fn unwrap_pulley_host_call(self) -> HostCall { + match self { + Self::PulleyHostCall(host_call) => host_call, + _ => panic!("`FuncKey::unwrap_pulley_host_call` called on {self:?}"), + } + } + + /// Unwrap a `FuncKey::ComponentTrampoline` or else panic. + #[cfg(feature = "component-model")] + pub fn unwrap_component_trampoline(self) -> component::TrampolineIndex { + match self { + Self::ComponentTrampoline(trampoline) => trampoline, + _ => panic!("`FuncKey::unwrap_component_trampoline` called on {self:?}"), + } + } + + /// Unwrap a `FuncKey::ResourceDropTrampoline` or else panic. + #[cfg(feature = "component-model")] + pub fn unwrap_resource_drop_trampoline(self) { + match self { + Self::ResourceDropTrampoline => {} + _ => panic!("`FuncKey::unwrap_resource_drop_trampoline` called on {self:?}"), + } + } +} diff --git a/crates/environ/src/compile/mod.rs b/crates/environ/src/compile/mod.rs index c4059cd96..ad35b2a45 100644 --- a/crates/environ/src/compile/mod.rs +++ b/crates/environ/src/compile/mod.rs @@ -3,8 +3,8 @@ use crate::prelude::*; use crate::{ - BuiltinFunctionIndex, DefinedFuncIndex, FlagValue, FuncIndex, FunctionLoc, ObjectKind, - PrimaryMap, StaticModuleIndex, TripleExt, WasmError, WasmFuncType, + DefinedFuncIndex, FlagValue, FunctionLoc, ObjectKind, PrimaryMap, StaticModuleIndex, TripleExt, + WasmError, WasmFuncType, }; use crate::{Tunables, obj}; use anyhow::Result; @@ -17,6 +17,7 @@ use std::path; use std::sync::Arc; mod address_map; +mod key; mod module_artifacts; mod module_environ; mod module_types; @@ -24,6 +25,7 @@ mod stack_maps; mod trap_encoding; pub use self::address_map::*; +pub use self::key::*; pub use self::module_artifacts::*; pub use self::module_environ::*; pub use self::module_types::*; @@ -70,19 +72,6 @@ impl core::error::Error for CompileError { } } -/// What relocations can be applied against. -/// -/// Each wasm function may refer to various other `RelocationTarget` entries. -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub enum RelocationTarget { - /// This is a reference to another defined wasm function in the same module. - Wasm(FuncIndex), - /// This is a reference to a trampoline for a builtin function. - Builtin(BuiltinFunctionIndex), - /// A pulley->host call from the interpreter. - PulleyHostcall(u32), -} - /// Implementation of an incremental compilation's key/value cache store. /// /// In theory, this could just be Cranelift's `CacheKvStore` trait, but it is not as we want to @@ -259,7 +248,7 @@ pub trait Compiler: Send + Sync { fn compile_function( &self, translation: &ModuleTranslation<'_>, - index: DefinedFuncIndex, + key: FuncKey, data: FunctionBodyData<'_>, types: &ModuleTypesBuilder, symbol: &str, @@ -274,7 +263,7 @@ pub trait Compiler: Send + Sync { &self, translation: &ModuleTranslation<'_>, types: &ModuleTypesBuilder, - index: DefinedFuncIndex, + key: FuncKey, symbol: &str, ) -> Result; @@ -286,6 +275,7 @@ pub trait Compiler: Send + Sync { fn compile_wasm_to_array_trampoline( &self, wasm_func_ty: &WasmFuncType, + key: FuncKey, symbol: &str, ) -> Result; @@ -300,7 +290,7 @@ pub trait Compiler: Send + Sync { /// call. fn compile_wasm_to_builtin( &self, - index: BuiltinFunctionIndex, + key: FuncKey, symbol: &str, ) -> Result; @@ -309,7 +299,7 @@ pub trait Compiler: Send + Sync { fn compiled_function_relocation_targets<'a>( &'a self, func: &'a dyn Any, - ) -> Box + 'a>; + ) -> Box + 'a>; /// Appends a list of compiled functions to an in-memory object. /// @@ -342,7 +332,7 @@ pub trait Compiler: Send + Sync { &self, obj: &mut Object<'static>, funcs: &[(String, Box)], - resolve_reloc: &dyn Fn(usize, RelocationTarget) -> usize, + resolve_reloc: &dyn Fn(usize, FuncKey) -> usize, ) -> Result>; /// Creates a new `Object` file which is used to build the results of a @@ -469,7 +459,7 @@ pub trait Compiler: Send + Sync { /// An inlining compiler. pub trait InliningCompiler: Sync + Send { /// Enumerate the function calls that the given `func` makes. - fn calls(&self, func: &CompiledFunctionBody, calls: &mut IndexSet) -> Result<()>; + fn calls(&self, func: &CompiledFunctionBody, calls: &mut IndexSet) -> Result<()>; /// Get the abstract size of the given function, for the purposes of /// inlining heuristics. @@ -483,7 +473,7 @@ pub trait InliningCompiler: Sync + Send { fn inline<'a>( &self, func: &mut CompiledFunctionBody, - get_callee: &'a mut dyn FnMut(FuncIndex) -> Option<&'a CompiledFunctionBody>, + get_callee: &'a mut dyn FnMut(FuncKey) -> Option<&'a CompiledFunctionBody>, ) -> Result<()>; /// Finish compiling the given function. diff --git a/crates/environ/src/compile/module_environ.rs b/crates/environ/src/compile/module_environ.rs index 9347cfca0..fb4b98d8c 100644 --- a/crates/environ/src/compile/module_environ.rs +++ b/crates/environ/src/compile/module_environ.rs @@ -37,14 +37,17 @@ pub struct ModuleEnvironment<'a, 'data> { tunables: &'a Tunables, } -/// The result of translating via `ModuleEnvironment`. Function bodies are not -/// yet translated, and data initializers have not yet been copied out of the -/// original buffer. -#[derive(Default)] +/// The result of translating via `ModuleEnvironment`. +/// +/// Function bodies are not yet translated, and data initializers have not yet +/// been copied out of the original buffer. pub struct ModuleTranslation<'data> { /// Module information. pub module: Module, + /// This module's index. + pub module_index: StaticModuleIndex, + /// The input wasm binary. /// /// This can be useful, for example, when modules are parsed from a @@ -109,6 +112,27 @@ pub struct ModuleTranslation<'data> { } impl<'data> ModuleTranslation<'data> { + /// Create a new translation for the module with the given index. + pub fn new(module_index: StaticModuleIndex) -> Self { + Self { + module_index, + module: Module::default(), + wasm: &[], + function_body_inputs: PrimaryMap::default(), + known_imported_functions: SecondaryMap::default(), + exported_signatures: Vec::default(), + debuginfo: DebugInfoData::default(), + has_unparsed_debuginfo: false, + data: Vec::default(), + data_align: None, + total_data: 0, + passive_data: Vec::default(), + total_passive_data: 0, + code_index: 0, + types: None, + } + } + /// Returns a reference to the type information of the current module. pub fn get_types(&self) -> &Types { self.types @@ -174,9 +198,10 @@ impl<'a, 'data> ModuleEnvironment<'a, 'data> { tunables: &'a Tunables, validator: &'a mut Validator, types: &'a mut ModuleTypesBuilder, + module_index: StaticModuleIndex, ) -> Self { Self { - result: ModuleTranslation::default(), + result: ModuleTranslation::new(module_index), types, tunables, validator, diff --git a/crates/environ/src/component/compiler.rs b/crates/environ/src/component/compiler.rs index b5278428b..1f0658bad 100644 --- a/crates/environ/src/component/compiler.rs +++ b/crates/environ/src/component/compiler.rs @@ -1,5 +1,5 @@ -use crate::component::{AllCallFunc, ComponentTranslation, ComponentTypesBuilder, TrampolineIndex}; -use crate::{CompiledFunctionBody, Tunables}; +use crate::component::{AllCallFunc, ComponentTranslation, ComponentTypesBuilder}; +use crate::{CompiledFunctionBody, FuncKey, Tunables}; use anyhow::Result; /// Compilation support necessary for components. @@ -14,7 +14,7 @@ pub trait ComponentCompiler: Send + Sync { &self, component: &ComponentTranslation, types: &ComponentTypesBuilder, - trampoline: TrampolineIndex, + key: FuncKey, tunables: &Tunables, symbol: &str, ) -> Result>; diff --git a/crates/environ/src/component/translate.rs b/crates/environ/src/component/translate.rs index ecdb0e421..3ff2bb4e7 100644 --- a/crates/environ/src/component/translate.rs +++ b/crates/environ/src/component/translate.rs @@ -1082,10 +1082,12 @@ impl<'a, 'data> Translator<'a, 'data> { } => { let index = self.validator.types(0).unwrap().module_count(); self.validator.module_section(&unchecked_range)?; + let static_module_index = self.static_modules.next_key(); let translation = ModuleEnvironment::new( self.tunables, self.validator, self.types.module_types_builder(), + static_module_index, ) .translate( parser, @@ -1101,12 +1103,13 @@ impl<'a, 'data> Translator<'a, 'data> { .context("wasm component contains an invalid module section") })?, )?; - let static_idx = self.static_modules.push(translation); + let static_module_index2 = self.static_modules.push(translation); + assert_eq!(static_module_index, static_module_index2); let types = self.validator.types(0).unwrap(); let ty = types.module_at(index); self.result .initializers - .push(LocalInitializer::ModuleStatic(static_idx, ty)); + .push(LocalInitializer::ModuleStatic(static_module_index, ty)); return Ok(Action::Skip(unchecked_range.end - unchecked_range.start)); } diff --git a/crates/environ/src/component/translate/adapt.rs b/crates/environ/src/component/translate/adapt.rs index 37f1a9284..c85163aaa 100644 --- a/crates/environ/src/component/translate/adapt.rs +++ b/crates/environ/src/component/translate/adapt.rs @@ -231,10 +231,12 @@ impl<'data> Translator<'_, 'data> { // likely to use that if anything is actually indirected through // memory. self.validator.reset(); + let static_module_index = self.static_modules.next_key(); let translation = ModuleEnvironment::new( self.tunables, &mut self.validator, self.types.module_types_builder(), + static_module_index, ) .translate(Parser::new(0), wasm) .expect("invalid adapter module generated"); @@ -260,8 +262,9 @@ impl<'data> Translator<'_, 'data> { .zip(translation.module.imports()) .map(|(arg, (_, _, ty))| fact_import_to_core_def(component, arg, ty)) .collect::>(); - let static_index = self.static_modules.push(translation); - let id = component.adapter_modules.push((static_index, args)); + let static_module_index2 = self.static_modules.push(translation); + assert_eq!(static_module_index, static_module_index2); + let id = component.adapter_modules.push((static_module_index, args)); assert_eq!(id, module_id); } } diff --git a/crates/environ/src/hostcall.rs b/crates/environ/src/hostcall.rs index b31331ada..0a57fb57e 100644 --- a/crates/environ/src/hostcall.rs +++ b/crates/environ/src/hostcall.rs @@ -8,6 +8,7 @@ use crate::component::ComponentBuiltinFunctionIndex; /// This type is intended to be serialized into a 32-bit index (or smaller) and /// is used by Pulley for example to identify how transitions from the guest to /// the host are performed. +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum HostCall { /// An "array call" is being done which means that the wasm is calling the /// host using the array calling convention (e.g. `VMArrayCallNative`). @@ -43,6 +44,28 @@ impl HostCall { HostCall::ComponentBuiltin(i) => 2 + BuiltinFunctionIndex::len() + i.index(), } } + + /// Create a `HostCall` from the result of an earlier call to + /// `HostCall::index`. + pub fn from_index(index: u32) -> Self { + let host_call = match index { + 0 => Self::ArrayCall, + _ if index < 1 + BuiltinFunctionIndex::len() => { + Self::Builtin(BuiltinFunctionIndex::from_u32(index - 1)) + } + #[cfg(feature = "component-model")] + _ if index == 1 + BuiltinFunctionIndex::len() => Self::ComponentLowerImport, + #[cfg(feature = "component-model")] + _ if index < 2 + BuiltinFunctionIndex::len() + ComponentBuiltinFunctionIndex::len() => { + Self::ComponentBuiltin(ComponentBuiltinFunctionIndex::from_u32( + index - 2 - BuiltinFunctionIndex::len(), + )) + } + _ => panic!("bad host call index: {index}"), + }; + debug_assert_eq!(index, host_call.index()); + host_call + } } impl From for HostCall { diff --git a/crates/environ/src/module_artifacts.rs b/crates/environ/src/module_artifacts.rs index 0d41a68f8..974b4f0fc 100644 --- a/crates/environ/src/module_artifacts.rs +++ b/crates/environ/src/module_artifacts.rs @@ -9,7 +9,7 @@ use core::str; use serde_derive::{Deserialize, Serialize}; /// Secondary in-memory results of function compilation. -#[derive(Serialize, Deserialize)] +#[derive(Clone, Serialize, Deserialize)] pub struct CompiledFunctionInfo { /// Where this function was found in the original wasm file. pub start_srcloc: FilePos, diff --git a/crates/wasmtime/src/compile.rs b/crates/wasmtime/src/compile.rs index 8325c6eaa..d6bc799de 100644 --- a/crates/wasmtime/src/compile.rs +++ b/crates/wasmtime/src/compile.rs @@ -29,25 +29,20 @@ use crate::prelude::*; use std::{ any::Any, borrow::Cow, - collections::{BTreeMap, BTreeSet, btree_map}, + collections::{BTreeMap, BTreeSet}, mem, ops::Range, }; use call_graph::CallGraph; -use wasmtime_environ::CompiledFunctionBody; -use wasmtime_environ::FuncIndex; -use wasmtime_environ::InliningCompiler; -use wasmtime_environ::IntraModuleInlining; -use wasmtime_environ::Tunables; -#[cfg(feature = "component-model")] -use wasmtime_environ::component::Translator; use wasmtime_environ::{ - BuiltinFunctionIndex, CompiledFunctionInfo, CompiledModuleInfo, Compiler, DefinedFuncIndex, - FilePos, FinishedObject, FunctionBodyData, ModuleEnvironment, ModuleInternedTypeIndex, - ModuleTranslation, ModuleTypes, ModuleTypesBuilder, ObjectKind, PrimaryMap, RelocationTarget, - StaticModuleIndex, + BuiltinFunctionIndex, CompiledFunctionBody, CompiledFunctionInfo, CompiledModuleInfo, Compiler, + DefinedFuncIndex, FilePos, FinishedObject, FuncKey, FunctionBodyData, InliningCompiler, + IntraModuleInlining, ModuleEnvironment, ModuleTranslation, ModuleTypes, ModuleTypesBuilder, + ObjectKind, PrimaryMap, SecondaryMap, StaticModuleIndex, Tunables, }; +#[cfg(feature = "component-model")] +use wasmtime_environ::{FunctionLoc, component::Translator}; mod call_graph; mod scc; @@ -87,9 +82,14 @@ pub(crate) fn build_artifacts( let mut validator = wasmparser::Validator::new_with_features(engine.features()); parser.set_features(*validator.features()); let mut types = ModuleTypesBuilder::new(&validator); - let mut translation = ModuleEnvironment::new(tunables, &mut validator, &mut types) - .translate(parser, wasm) - .context("failed to parse WebAssembly module")?; + let mut translation = ModuleEnvironment::new( + tunables, + &mut validator, + &mut types, + StaticModuleIndex::from_u32(0), + ) + .translate(parser, wasm) + .context("failed to parse WebAssembly module")?; let functions = mem::take(&mut translation.function_body_inputs); let compile_inputs = CompileInputs::for_module(&types, &translation, functions); @@ -200,8 +200,7 @@ pub(crate) fn build_component_artifacts( let info = CompiledComponentInfo { component: component.component, trampolines: compilation_artifacts.trampolines, - resource_drop_wasm_to_array_trampoline: compilation_artifacts - .resource_drop_wasm_to_array_trampoline, + resource_drop_wasm_to_array_trampoline: compilation_artifacts.resource_drop_trampoline, }; let artifacts = ComponentArtifacts { info, @@ -217,145 +216,6 @@ pub(crate) fn build_component_artifacts( type CompileInput<'a> = Box Result> + Send + 'a>; -/// A sortable, comparable key for a compilation output. -/// -/// Two `u32`s to align with `cranelift_codegen::ir::UserExternalName`. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -struct CompileKey { - // The namespace field is bitpacked like: - // - // [ kind:i3 module:i29 ] - namespace: u32, - - index: u32, -} - -#[repr(u32)] -#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] -enum CompileKind { - WasmFunction = CompileKey::new_kind(0), - ArrayToWasmTrampoline = CompileKey::new_kind(1), - WasmToArrayTrampoline = CompileKey::new_kind(2), - WasmToBuiltinTrampoline = CompileKey::new_kind(3), - - #[cfg(feature = "component-model")] - Trampoline = CompileKey::new_kind(4), - #[cfg(feature = "component-model")] - ResourceDropWasmToArrayTrampoline = CompileKey::new_kind(5), -} - -impl From for u32 { - fn from(kind: CompileKind) -> Self { - kind as u32 - } -} - -impl core::fmt::Debug for CompileKey { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - f.debug_struct("CompileKey") - .field("kind", &self.kind()) - .field("module", &self.module()) - .field("index", &self.index) - .finish() - } -} - -impl CompileKey { - const KIND_BITS: u32 = 3; - const KIND_OFFSET: u32 = 32 - Self::KIND_BITS; - const KIND_MASK: u32 = ((1 << Self::KIND_BITS) - 1) << Self::KIND_OFFSET; - - const fn new_kind(kind: u32) -> u32 { - assert!(kind < (1 << Self::KIND_BITS)); - kind << Self::KIND_OFFSET - } - - fn kind(&self) -> CompileKind { - let k = self.namespace & Self::KIND_MASK; - if k == u32::from(CompileKind::WasmFunction) { - return CompileKind::WasmFunction; - } - if k == u32::from(CompileKind::ArrayToWasmTrampoline) { - return CompileKind::ArrayToWasmTrampoline; - } - if k == u32::from(CompileKind::WasmToArrayTrampoline) { - return CompileKind::WasmToArrayTrampoline; - } - if k == u32::from(CompileKind::WasmToBuiltinTrampoline) { - return CompileKind::WasmToBuiltinTrampoline; - } - - #[cfg(feature = "component-model")] - { - if k == u32::from(CompileKind::Trampoline) { - return CompileKind::Trampoline; - } - if k == u32::from(CompileKind::ResourceDropWasmToArrayTrampoline) { - return CompileKind::ResourceDropWasmToArrayTrampoline; - } - } - - unreachable!() - } - - fn module(&self) -> StaticModuleIndex { - StaticModuleIndex::from_u32(self.namespace & !Self::KIND_MASK) - } - - fn defined_func_index(&self) -> DefinedFuncIndex { - DefinedFuncIndex::from_u32(self.index) - } - - // NB: more kinds in the other `impl` block. - - fn wasm_function(module: StaticModuleIndex, index: DefinedFuncIndex) -> Self { - debug_assert_eq!(module.as_u32() & Self::KIND_MASK, 0); - Self { - namespace: u32::from(CompileKind::WasmFunction) | module.as_u32(), - index: index.as_u32(), - } - } - - fn array_to_wasm_trampoline(module: StaticModuleIndex, index: DefinedFuncIndex) -> Self { - debug_assert_eq!(module.as_u32() & Self::KIND_MASK, 0); - Self { - namespace: u32::from(CompileKind::ArrayToWasmTrampoline) | module.as_u32(), - index: index.as_u32(), - } - } - - fn wasm_to_array_trampoline(index: ModuleInternedTypeIndex) -> Self { - Self { - namespace: CompileKind::WasmToArrayTrampoline.into(), - index: index.as_u32(), - } - } - - fn wasm_to_builtin_trampoline(index: BuiltinFunctionIndex) -> Self { - Self { - namespace: CompileKind::WasmToBuiltinTrampoline.into(), - index: index.index(), - } - } -} - -#[cfg(feature = "component-model")] -impl CompileKey { - fn trampoline(index: wasmtime_environ::component::TrampolineIndex) -> Self { - Self { - namespace: CompileKind::Trampoline.into(), - index: index.as_u32(), - } - } - - fn resource_drop_wasm_to_array_trampoline() -> Self { - Self { - namespace: CompileKind::ResourceDropWasmToArrayTrampoline.into(), - index: 0, - } - } -} - #[derive(Clone, Copy)] enum CompiledFunction { Function(T), @@ -405,11 +265,15 @@ impl From> for CompiledFunction { - key: CompileKey, + key: FuncKey, symbol: String, function: CompiledFunction, start_srcloc: FilePos, + + // Only present when `self.key` is a `FuncKey::DefinedWasmFunction(..)`. translation: Option<&'a ModuleTranslation<'a>>, + + // Only present when `self.key` is a `FuncKey::DefinedWasmFunction(..)`. func_body: Option>, } @@ -475,12 +339,13 @@ impl<'a> CompileInputs<'a> { for (idx, trampoline) in component.trampolines.iter() { ret.push_input(move |compiler| { + let key = FuncKey::ComponentTrampoline(idx); let symbol = trampoline.symbol_name(); Ok(CompileOutput { - key: CompileKey::trampoline(idx), + key, function: compiler .component_compiler() - .compile_trampoline(component, types, idx, tunables, &symbol) + .compile_trampoline(component, types, key, tunables, &symbol) .with_context(|| format!("failed to compile {symbol}"))? .into(), symbol, @@ -500,12 +365,13 @@ impl<'a> CompileInputs<'a> { if component.component.num_resources > 0 { if let Some(sig) = types.find_resource_drop_signature() { ret.push_input(move |compiler| { + let key = FuncKey::ResourceDropTrampoline; let symbol = "resource_drop_trampoline".to_string(); let function = compiler - .compile_wasm_to_array_trampoline(types[sig].unwrap_func(), &symbol) + .compile_wasm_to_array_trampoline(types[sig].unwrap_func(), key, &symbol) .with_context(|| format!("failed to compile `{symbol}`"))?; Ok(CompileOutput { - key: CompileKey::resource_drop_wasm_to_array_trampoline(), + key, function: CompiledFunction::Function(function), symbol, start_srcloc: FilePos::default(), @@ -563,6 +429,7 @@ impl<'a> CompileInputs<'a> { for (module, translation, functions) in translations { for (def_func_index, func_body_data) in functions { self.push_input(move |compiler| { + let key = FuncKey::DefinedWasmFunction(module, def_func_index); let func_index = translation.module.func_index(def_func_index); let symbol = match translation .debuginfo @@ -587,17 +454,11 @@ impl<'a> CompileInputs<'a> { let offset = data.original_position(); let start_srcloc = FilePos::new(u32::try_from(offset).unwrap()); let function = compiler - .compile_function( - translation, - def_func_index, - func_body_data, - types, - &symbol, - ) + .compile_function(translation, key, func_body_data, types, &symbol) .with_context(|| format!("failed to compile: {symbol}"))?; Ok(CompileOutput { - key: CompileKey::wasm_function(module, def_func_index), + key, symbol, function: CompiledFunction::Function(function), start_srcloc, @@ -609,6 +470,7 @@ impl<'a> CompileInputs<'a> { let func_index = translation.module.func_index(def_func_index); if translation.module.functions[func_index].is_escaping() { self.push_input(move |compiler| { + let key = FuncKey::ArrayToWasmTrampoline(module, def_func_index); let func_index = translation.module.func_index(def_func_index); let symbol = format!( "wasm[{}]::array_to_wasm_trampoline[{}]", @@ -616,15 +478,10 @@ impl<'a> CompileInputs<'a> { func_index.as_u32() ); let trampoline = compiler - .compile_array_to_wasm_trampoline( - translation, - types, - def_func_index, - &symbol, - ) + .compile_array_to_wasm_trampoline(translation, types, key, &symbol) .with_context(|| format!("failed to compile: {symbol}"))?; Ok(CompileOutput { - key: CompileKey::array_to_wasm_trampoline(module, def_func_index), + key, symbol, function: CompiledFunction::Function(trampoline), start_srcloc: FilePos::default(), @@ -644,15 +501,16 @@ impl<'a> CompileInputs<'a> { } let trampoline_func_ty = types[trampoline_type_index].unwrap_func(); self.push_input(move |compiler| { + let key = FuncKey::WasmToArrayTrampoline(trampoline_type_index); let symbol = format!( "signatures[{}]::wasm_to_array_trampoline", trampoline_type_index.as_u32() ); let trampoline = compiler - .compile_wasm_to_array_trampoline(trampoline_func_ty, &symbol) + .compile_wasm_to_array_trampoline(trampoline_func_ty, key, &symbol) .with_context(|| format!("failed to compile: {symbol}"))?; Ok(CompileOutput { - key: CompileKey::wasm_to_array_trampoline(trampoline_type_index), + key, function: CompiledFunction::Function(trampoline), symbol, start_srcloc: FilePos::default(), @@ -731,9 +589,9 @@ the use case. compile_required_builtins(engine, &mut raw_outputs)?; // Bucket the outputs by kind. - let mut outputs: BTreeMap> = BTreeMap::new(); + let mut outputs: BTreeMap = BTreeMap::new(); for output in raw_outputs { - outputs.entry(output.key.kind()).or_default().push(output); + outputs.insert(output.key, output); } Ok(UnlinkedCompileOutputs { outputs }) @@ -761,12 +619,9 @@ the use case. fn wasm_functions<'a>( outputs: &'a PrimaryMap>>, ) -> impl Iterator + 'a { - outputs.iter().filter_map(|(i, o)| { - if o.as_ref()?.key.kind() == CompileKind::WasmFunction { - Some(i) - } else { - None - } + outputs.iter().filter_map(|(i, o)| match o.as_ref()?.key { + FuncKey::DefinedWasmFunction(..) => Some(i), + _ => None, }) } @@ -780,11 +635,15 @@ the use case. // module. This map enables that translation. let pair_to_output: HashMap<(StaticModuleIndex, DefinedFuncIndex), OutputIndex> = outputs .iter() - .filter(|(_, output)| output.as_ref().unwrap().key.kind() == CompileKind::WasmFunction) + .filter(|(_, output)| { + matches!( + output.as_ref().unwrap().key, + FuncKey::DefinedWasmFunction(..) + ) + }) .map(|(output_index, output)| { let output = output.as_ref().unwrap(); - let module_index = output.key.module(); - let defined_func_index = output.key.defined_func_index(); + let (module_index, defined_func_index) = output.key.unwrap_defined_wasm_function(); ((module_index, defined_func_index), output_index) }) .collect(); @@ -795,14 +654,14 @@ the use case. // trampolines being in their own stack frame when we save the entry and // exit SP, FP, and PC for backtraces in trampolines. let call_graph = CallGraph::::new(wasm_functions(&outputs), { - let mut func_indices = IndexSet::default(); + let mut compile_keys = IndexSet::default(); let outputs = &outputs; let pair_to_output = &pair_to_output; move |output_index, calls| { debug_assert!(calls.is_empty()); let output = outputs[output_index].as_ref().unwrap(); - debug_assert_eq!(output.key.kind(), CompileKind::WasmFunction); + debug_assert!(matches!(output.key, FuncKey::DefinedWasmFunction(..))); let func = match &output.function { CompiledFunction::Function(f) => f, @@ -812,31 +671,17 @@ the use case. } }; - // Get this function's call graph edges as `FuncIndex`es. - func_indices.clear(); - inlining_compiler.calls(func, &mut func_indices)?; + // Get this function's call graph edges as `CompileKey`s. + compile_keys.clear(); + inlining_compiler.calls(func, &mut compile_keys)?; // Translate each of those to (module, defined-function-index) // pairs and then finally to output indices, which is what we // actually need. - let caller_module = output.key.module(); - let translation = output - .translation - .expect("all wasm functions have translations"); - calls.extend(func_indices.iter().copied().filter_map(|callee_func| { - if let Some(callee_def_func) = - translation.module.defined_func_index(callee_func) - { - // Call to a function in the same module. - Some(pair_to_output[&(caller_module, callee_def_func)]) - } else if let Some(pair) = translation.known_imported_functions[callee_func] { - // Call to a statically-known imported function. - Some(pair_to_output[&pair]) + calls.extend(compile_keys.iter().copied().filter_map(|key| { + if let FuncKey::DefinedWasmFunction(module, def_func) = key { + Some(pair_to_output[&(module, def_func)]) } else { - // Call to an unknown imported function or perhaps to - // multiple different functions in different - // instantiations. Can't inline these calls, so don't - // add them to the call graph. None } })); @@ -868,12 +713,12 @@ the use case. engine.run_maybe_parallel_mut( &mut layer_outputs, |output: &mut CompileOutput<'_>| { - debug_assert_eq!(output.key.kind(), CompileKind::WasmFunction); log::trace!("processing inlining for {:?}", output.key); + debug_assert!(matches!(output.key, FuncKey::DefinedWasmFunction(..))); let caller_translation = output.translation.unwrap(); - let caller_module = output.key.module(); - let caller_def_func = output.key.defined_func_index(); + let (caller_module, caller_def_func) = + output.key.unwrap_defined_wasm_function(); let caller_needs_gc_heap = caller_translation.module.needs_gc_heap; let caller = output @@ -883,40 +728,31 @@ the use case. let mut caller_size = inlining_compiler.size(caller); - inlining_compiler.inline(caller, &mut |callee: FuncIndex| { - let (callee_module, callee_def_func, callee_needs_gc_heap) = - if let Some(def_func) = - caller_translation.module.defined_func_index(callee) - { - (caller_module, def_func, Some(caller_needs_gc_heap)) - } else { - let (def_module, def_func) = caller_translation - .known_imported_functions[callee] - .unwrap_or_else(|| { - panic!( - "a direct call to an imported function must have a \ - statically-known definition, but direct call to imported \ - function {callee:?} has no statically-known definition", - ) - }); - (def_module, def_func, None) - }; - + inlining_compiler.inline(caller, &mut |callee_key: FuncKey| { + let (callee_module, callee_def_func) = + callee_key.unwrap_defined_wasm_function(); let callee_output_index: OutputIndex = pair_to_output[&(callee_module, callee_def_func)]; + + // NB: If the callee is not inside `outputs`, then it is + // in the same `Strata` layer as the caller (and + // therefore is in the same strongly-connected component + // as the caller, and they mutually recursive). In this + // case, we do not do any inlining; communicate this + // command via `?`-propagation. let callee_output = outputs[callee_output_index].as_ref()?; - let callee_needs_gc_heap = callee_needs_gc_heap.unwrap_or_else(|| { - callee_output.translation.unwrap().module.needs_gc_heap - }); - debug_assert_eq!(callee_output.key.kind(), CompileKind::WasmFunction); + debug_assert_eq!(callee_output.key, callee_key); + let callee = callee_output .function .as_function() .expect("wasm functions are not all-call functions"); - let callee_size = inlining_compiler.size(callee); + let callee_needs_gc_heap = + callee_output.translation.unwrap().module.needs_gc_heap; + if Self::should_inline(InlineHeuristicParams { tunables: engine.tunables(), caller_size, @@ -1078,15 +914,16 @@ fn compile_required_builtins(engine: &Engine, raw_outputs: &mut Vec continue, }; for reloc in compiler.compiled_function_relocation_targets(&*f.code) { - match reloc { - RelocationTarget::Builtin(i) => { - if builtins.insert(i) { - new_inputs.push(compile_builtin(i)); - } + if let FuncKey::WasmToBuiltinTrampoline(builtin) = reloc { + if builtins.insert(builtin) { + new_inputs.push(compile_builtin(builtin)); } - _ => {} } } } @@ -1120,7 +954,7 @@ fn compile_required_builtins(engine: &Engine, raw_outputs: &mut Vec { // A map from kind to `CompileOutput`. - outputs: BTreeMap>>, + outputs: BTreeMap>, } impl UnlinkedCompileOutputs<'_> { @@ -1136,7 +970,7 @@ impl UnlinkedCompileOutputs<'_> { let mut indices = FunctionIndices::default(); let mut needs_gc_heap = false; - for output in self.outputs.into_iter().flat_map(|(_kind, outs)| outs) { + for output in self.outputs.into_values() { let index = match output.function { CompiledFunction::Function(f) => { needs_gc_heap |= f.needs_gc_heap; @@ -1164,22 +998,18 @@ impl UnlinkedCompileOutputs<'_> { } }; - if output.key.kind() == CompileKind::WasmFunction - || output.key.kind() == CompileKind::ArrayToWasmTrampoline + if let FuncKey::DefinedWasmFunction(module, _) + | FuncKey::ArrayToWasmTrampoline(module, _) = output.key { indices .compiled_func_index_to_module - .insert(index.unwrap_function(), output.key.module()); + .insert(index.unwrap_function(), module); indices .start_srclocs .insert(output.key, output.start_srcloc); } - indices - .indices - .entry(output.key.kind()) - .or_default() - .insert(output.key, index); + indices.indices.insert(output.key, index); } PreLinkOutput { @@ -1209,17 +1039,17 @@ struct FunctionIndices { compiled_func_index_to_module: HashMap, // A map of wasm functions and where they're located in the original file. - start_srclocs: HashMap, + start_srclocs: HashMap, - // The index of each compiled function, bucketed by compile key kind. - indices: BTreeMap>>, + // The index of each compiled function. + indices: BTreeMap>, } impl FunctionIndices { /// Link the compiled functions together, resolving relocations, and append /// them to the given ELF file. fn link_and_append_code<'a>( - mut self, + self, types: &ModuleTypesBuilder, mut obj: object::write::Object<'static>, engine: &'a Engine, @@ -1237,36 +1067,13 @@ impl FunctionIndices { let symbol_ids_and_locs = compiler.append_code( &mut obj, &compiled_funcs, - &|caller_index: usize, callee: RelocationTarget| match callee { - RelocationTarget::Wasm(callee_index) => { - let caller_module = self - .compiled_func_index_to_module - .get(&caller_index) - .copied() - .expect("should only reloc inside wasm function callers"); - let key = if let Some(def_func_index) = translations[caller_module] - .module - .defined_func_index(callee_index) - { - CompileKey::wasm_function(caller_module, def_func_index) - } else { - let (def_module, def_func_index) = translations[caller_module] - .known_imported_functions[callee_index] - .expect( - "a direct call to an imported function must have a \ - statically-known import", - ); - CompileKey::wasm_function(def_module, def_func_index) - }; - self.indices[&CompileKind::WasmFunction][&key].unwrap_function() - } - RelocationTarget::Builtin(builtin) => self.indices - [&CompileKind::WasmToBuiltinTrampoline] - [&CompileKey::wasm_to_builtin_trampoline(builtin)] - .unwrap_function(), - RelocationTarget::PulleyHostcall(_) => { - unreachable!("relocation is resolved at runtime, not compile time"); - } + &|_caller_index: usize, callee: FuncKey| { + self.indices + .get(&callee) + .and_then(|f| f.as_function().copied()) + .unwrap_or_else(|| { + panic!("cannot resolve relocation! no index for callee {callee:?}") + }) }, )?; @@ -1276,106 +1083,124 @@ impl FunctionIndices { &mut obj, &translations, &|module, func| { - let bucket = &self.indices[&CompileKind::WasmFunction]; - let i = bucket[&CompileKey::wasm_function(module, func)].unwrap_function(); - (symbol_ids_and_locs[i].0, &*compiled_funcs[i].1) + let i = + self.indices[&FuncKey::DefinedWasmFunction(module, func)].unwrap_function(); + let (symbol, _) = symbol_ids_and_locs[i]; + let (_, compiled_func) = &compiled_funcs[i]; + (symbol, &**compiled_func) }, dwarf_package_bytes, tunables, )?; } - let mut obj = wasmtime_environ::ObjectBuilder::new(obj, tunables); - let mut artifacts = Artifacts::default(); - - // Remove this as it's not needed by anything below and we'll debug - // assert `self.indices` is empty, so this is acknowledgement that this - // is a pure runtime implementation detail and not needed in any - // metadata generated below. - self.indices.remove(&CompileKind::WasmToBuiltinTrampoline); - - // Finally, build our binary artifacts that map things like `FuncIndex` - // to a function location and all of that using the indices we saved - // earlier and the function locations we just received after appending - // the code. - - let mut wasm_functions = self - .indices - .remove(&CompileKind::WasmFunction) - .unwrap_or_default() - .into_iter() - .peekable(); - - fn wasm_functions_for_module( - wasm_functions: &mut std::iter::Peekable< - btree_map::IntoIter>, - >, - module: StaticModuleIndex, - ) -> impl Iterator)> + '_ { - std::iter::from_fn(move || { - let (key, _) = wasm_functions.peek()?; - if key.module() == module { - wasm_functions.next() - } else { - None + let mut def_funcs = SecondaryMap::< + StaticModuleIndex, + PrimaryMap, + >::new(); + + #[cfg(feature = "component-model")] + let mut trampolines = PrimaryMap::< + wasmtime_environ::component::TrampolineIndex, + wasmtime_environ::component::AllCallFunc, + >::new(); + + #[cfg(feature = "component-model")] + let mut resource_drop_trampoline = None; + + for (key, index) in &self.indices { + // NB: exhaustively match on function keys to make sure that we are + // remembering to handle everything we are compiling when doing this + // final linking and metadata-collection step. + match *key { + FuncKey::DefinedWasmFunction(module, def_func) => { + let index = index.unwrap_function(); + let (_, wasm_func_loc) = symbol_ids_and_locs[index]; + let start_srcloc = self.start_srclocs[key]; + + let array_to_wasm_trampoline = self + .indices + .get(&FuncKey::ArrayToWasmTrampoline(module, def_func)) + .map(|index| { + let index = index.unwrap_function(); + let (_, loc) = symbol_ids_and_locs[index]; + loc + }); + + debug_assert!(def_funcs[module].get(def_func).is_none()); + let def_func2 = def_funcs[module].push(CompiledFunctionInfo { + start_srcloc, + wasm_func_loc, + array_to_wasm_trampoline, + }); + debug_assert_eq!(def_func, def_func2); + } + + FuncKey::ArrayToWasmTrampoline(module, def_func) => { + // These are handled by the `DefinedWasmFunction` arm above. + debug_assert!(def_funcs[module].get(def_func).is_some()); + } + + FuncKey::WasmToArrayTrampoline(_) => { + // These are handled in `modules` creation below. } - }) - } - let mut array_to_wasm_trampolines = self - .indices - .remove(&CompileKind::ArrayToWasmTrampoline) - .unwrap_or_default(); + FuncKey::WasmToBuiltinTrampoline(_) => { + // Nothing we need to do for these: they are only called by + // Wasm functions, and we never create `funcref`s containing + // them, so we don't need to keep any metadata for them or + // anything like that. + } - // NB: unlike the above maps this is not emptied out during iteration - // since each module may reach into different portions of this map. - let wasm_to_array_trampolines = self - .indices - .remove(&CompileKind::WasmToArrayTrampoline) - .unwrap_or_default(); + FuncKey::PulleyHostCall(_) => { + unreachable!("we don't compile any artifacts for Pulley host calls") + } - artifacts.modules = translations + #[cfg(feature = "component-model")] + FuncKey::ComponentTrampoline(trampoline) => { + let index = index.unwrap_all_call_func(); + let loc = index.map(|i| { + let (_, loc) = symbol_ids_and_locs[i]; + loc + }); + debug_assert!(trampolines.get(trampoline).is_none()); + let trampoline2 = trampolines.push(loc); + debug_assert_eq!(trampoline, trampoline2); + } + + #[cfg(feature = "component-model")] + FuncKey::ResourceDropTrampoline => { + let index = index.unwrap_function(); + let (_, loc) = symbol_ids_and_locs[index]; + resource_drop_trampoline = Some(loc); + } + } + } + + let mut obj = wasmtime_environ::ObjectBuilder::new(obj, tunables); + let modules = translations .into_iter() .map(|(module, mut translation)| { - // If configured attempt to use static memory initialization which - // can either at runtime be implemented as a single memcpy to - // initialize memory or otherwise enabling virtual-memory-tricks - // such as mmap'ing from a file to get copy-on-write. + let def_funcs = mem::take(&mut def_funcs[module]); + + // If configured attempt to use static memory initialization + // which can either at runtime be implemented as a single memcpy + // to initialize memory or otherwise enabling + // virtual-memory-tricks such as mmap'ing from a file to get + // copy-on-write. if engine.tunables().memory_init_cow { let align = compiler.page_size_align(); let max_always_allowed = engine.config().memory_guaranteed_dense_image_size; translation.try_static_init(align, max_always_allowed); } - // Attempt to convert table initializer segments to - // FuncTable representation where possible, to enable - // table lazy init. + // Attempt to convert table initializer segments to FuncTable + // representation where possible, to enable table lazy init. if engine.tunables().table_lazy_init { translation.try_func_table_init(); } - let funcs: PrimaryMap = - wasm_functions_for_module(&mut wasm_functions, module) - .map(|(key, wasm_func_index)| { - let wasm_func_index = wasm_func_index.unwrap_function(); - let wasm_func_loc = symbol_ids_and_locs[wasm_func_index].1; - let start_srcloc = self.start_srclocs.remove(&key).unwrap(); - - let array_to_wasm_trampoline = array_to_wasm_trampolines - .remove(&CompileKey::array_to_wasm_trampoline( - key.module(), - DefinedFuncIndex::from_u32(key.index), - )) - .map(|x| symbol_ids_and_locs[x.unwrap_function()].1); - - CompiledFunctionInfo { - start_srcloc, - wasm_func_loc, - array_to_wasm_trampoline, - } - }) - .collect(); - + // Gather this module's trampolines. let unique_and_sorted_trampoline_sigs = translation .module .types @@ -1385,43 +1210,27 @@ impl FunctionIndices { .map(|idx| types.trampoline_type(idx)) .collect::>(); let wasm_to_array_trampolines = unique_and_sorted_trampoline_sigs - .iter() - .map(|idx| { - let trampoline = types.trampoline_type(*idx); - let key = CompileKey::wasm_to_array_trampoline(trampoline); - let compiled = wasm_to_array_trampolines[&key]; - (*idx, symbol_ids_and_locs[compiled.unwrap_function()].1) + .into_iter() + .map(|ty| { + debug_assert_eq!(ty, types.trampoline_type(ty)); + let key = FuncKey::WasmToArrayTrampoline(ty); + let index = self.indices[&key].unwrap_function(); + let (_, loc) = symbol_ids_and_locs[index]; + (ty, loc) }) .collect(); - obj.append(translation, funcs, wasm_to_array_trampolines) + obj.append(translation, def_funcs, wasm_to_array_trampolines) }) .collect::>>()?; - #[cfg(feature = "component-model")] - { - artifacts.trampolines = self - .indices - .remove(&CompileKind::Trampoline) - .unwrap_or_default() - .into_iter() - .map(|(_id, x)| x.unwrap_all_call_func().map(|i| symbol_ids_and_locs[i].1)) - .collect(); - let map = self - .indices - .remove(&CompileKind::ResourceDropWasmToArrayTrampoline) - .unwrap_or_default(); - assert!(map.len() <= 1); - artifacts.resource_drop_wasm_to_array_trampoline = map - .into_iter() - .next() - .map(|(_id, x)| symbol_ids_and_locs[x.unwrap_function()].1); - } - - debug_assert!( - self.indices.is_empty(), - "Should have processed all compile outputs" - ); + let artifacts = Artifacts { + modules, + #[cfg(feature = "component-model")] + trampolines, + #[cfg(feature = "component-model")] + resource_drop_trampoline, + }; Ok((obj, artifacts)) } @@ -1438,7 +1247,7 @@ struct Artifacts { wasmtime_environ::component::AllCallFunc, >, #[cfg(feature = "component-model")] - resource_drop_wasm_to_array_trampoline: Option, + resource_drop_trampoline: Option, } impl Artifacts { diff --git a/crates/wasmtime/src/engine/serialization.rs b/crates/wasmtime/src/engine/serialization.rs index feccd9f5d..359595822 100644 --- a/crates/wasmtime/src/engine/serialization.rs +++ b/crates/wasmtime/src/engine/serialization.rs @@ -691,6 +691,8 @@ Caused by: #[test] #[cfg_attr(miri, ignore)] fn cache_accounts_for_opt_level() -> Result<()> { + let _ = env_logger::try_init(); + let td = TempDir::new()?; let config_path = td.path().join("config.toml"); std::fs::write( diff --git a/crates/winch/Cargo.toml b/crates/winch/Cargo.toml index 42e76aeaf..5a37c7541 100644 --- a/crates/winch/Cargo.toml +++ b/crates/winch/Cargo.toml @@ -21,6 +21,7 @@ cranelift-codegen = { workspace = true } wasmtime-cranelift = { workspace = true } wasmparser = { workspace = true } gimli = { workspace = true, features = ['std'] } +log = { workspace = true } [features] component-model = [ diff --git a/crates/winch/src/compiler.rs b/crates/winch/src/compiler.rs index 1b27f9669..41fb19ff6 100644 --- a/crates/winch/src/compiler.rs +++ b/crates/winch/src/compiler.rs @@ -7,9 +7,8 @@ use std::sync::Mutex; use wasmparser::FuncValidatorAllocations; use wasmtime_cranelift::CompiledFunction; use wasmtime_environ::{ - BuiltinFunctionIndex, CompileError, CompiledFunctionBody, DefinedFuncIndex, FunctionBodyData, - FunctionLoc, ModuleTranslation, ModuleTypesBuilder, PrimaryMap, RelocationTarget, - StaticModuleIndex, Tunables, VMOffsets, + CompileError, CompiledFunctionBody, DefinedFuncIndex, FuncKey, FunctionBodyData, FunctionLoc, + ModuleTranslation, ModuleTypesBuilder, PrimaryMap, StaticModuleIndex, Tunables, VMOffsets, }; use winch_codegen::{BuiltinFunctions, CallingConvention, TargetIsa}; @@ -88,6 +87,23 @@ impl Compiler { } } +fn box_dyn_any_compiled_function(f: CompiledFunction) -> Box { + let b = box_dyn_any(f); + debug_assert!(b.is::()); + b +} + +fn box_dyn_any(x: impl Any + Send + Sync) -> Box { + log::trace!( + "making Box of {}", + std::any::type_name_of_val(&x) + ); + let b = Box::new(x); + let r: &(dyn Any + Sync + Send) = &*b; + log::trace!(" --> {r:#p}"); + b +} + impl wasmtime_environ::Compiler for Compiler { fn inlining_compiler(&self) -> Option<&dyn wasmtime_environ::InliningCompiler> { None @@ -96,12 +112,17 @@ impl wasmtime_environ::Compiler for Compiler { fn compile_function( &self, translation: &ModuleTranslation<'_>, - index: DefinedFuncIndex, + key: FuncKey, data: FunctionBodyData<'_>, types: &ModuleTypesBuilder, - _symbol: &str, + symbol: &str, ) -> Result { - let index = translation.module.func_index(index); + log::trace!("compiling function: {key:?} = {symbol:?}"); + + let (module_index, def_func_index) = key.unwrap_defined_wasm_function(); + debug_assert_eq!(module_index, translation.module_index); + + let index = translation.module.func_index(def_func_index); let sig = translation.module.functions[index] .signature .unwrap_module_type_index(); @@ -138,7 +159,7 @@ impl wasmtime_environ::Compiler for Compiler { } Ok(CompiledFunctionBody { - code: Box::new(func), + code: box_dyn_any_compiled_function(func), // TODO: Winch doesn't support GC objects and stack maps and all that yet. needs_gc_heap: false, }) @@ -148,27 +169,28 @@ impl wasmtime_environ::Compiler for Compiler { &self, translation: &ModuleTranslation<'_>, types: &ModuleTypesBuilder, - index: DefinedFuncIndex, + key: FuncKey, symbol: &str, ) -> Result { self.trampolines - .compile_array_to_wasm_trampoline(translation, types, index, symbol) + .compile_array_to_wasm_trampoline(translation, types, key, symbol) } fn compile_wasm_to_array_trampoline( &self, wasm_func_ty: &wasmtime_environ::WasmFuncType, + key: FuncKey, symbol: &str, ) -> Result { self.trampolines - .compile_wasm_to_array_trampoline(wasm_func_ty, symbol) + .compile_wasm_to_array_trampoline(wasm_func_ty, key, symbol) } fn append_code( &self, obj: &mut Object<'static>, funcs: &[(String, Box)], - resolve_reloc: &dyn Fn(usize, wasmtime_environ::RelocationTarget) -> usize, + resolve_reloc: &dyn Fn(usize, wasmtime_environ::FuncKey) -> usize, ) -> Result> { self.trampolines.append_code(obj, funcs, resolve_reloc) } @@ -214,16 +236,16 @@ impl wasmtime_environ::Compiler for Compiler { fn compile_wasm_to_builtin( &self, - index: BuiltinFunctionIndex, + key: FuncKey, symbol: &str, ) -> Result { - self.trampolines.compile_wasm_to_builtin(index, symbol) + self.trampolines.compile_wasm_to_builtin(key, symbol) } fn compiled_function_relocation_targets<'a>( &'a self, func: &'a dyn Any, - ) -> Box + 'a> { + ) -> Box + 'a> { self.trampolines.compiled_function_relocation_targets(func) } } @@ -240,7 +262,7 @@ impl wasmtime_environ::Compiler for NoInlineCompiler { fn compile_function( &self, translation: &ModuleTranslation<'_>, - index: DefinedFuncIndex, + key: FuncKey, data: FunctionBodyData<'_>, types: &ModuleTypesBuilder, symbol: &str, @@ -248,7 +270,7 @@ impl wasmtime_environ::Compiler for NoInlineCompiler { let input = data.body.clone(); let mut body = self .0 - .compile_function(translation, index, data, types, symbol)?; + .compile_function(translation, key, data, types, symbol)?; if let Some(c) = self.0.inlining_compiler() { c.finish_compiling(&mut body, Some(input), symbol) .map_err(|e| CompileError::Codegen(e.to_string()))?; @@ -260,12 +282,12 @@ impl wasmtime_environ::Compiler for NoInlineCompiler { &self, translation: &ModuleTranslation<'_>, types: &ModuleTypesBuilder, - index: DefinedFuncIndex, + key: FuncKey, symbol: &str, ) -> Result { - let mut body = - self.0 - .compile_array_to_wasm_trampoline(translation, types, index, symbol)?; + let mut body = self + .0 + .compile_array_to_wasm_trampoline(translation, types, key, symbol)?; if let Some(c) = self.0.inlining_compiler() { c.finish_compiling(&mut body, None, symbol) .map_err(|e| CompileError::Codegen(e.to_string()))?; @@ -276,11 +298,12 @@ impl wasmtime_environ::Compiler for NoInlineCompiler { fn compile_wasm_to_array_trampoline( &self, wasm_func_ty: &wasmtime_environ::WasmFuncType, + key: FuncKey, symbol: &str, ) -> Result { let mut body = self .0 - .compile_wasm_to_array_trampoline(wasm_func_ty, symbol)?; + .compile_wasm_to_array_trampoline(wasm_func_ty, key, symbol)?; if let Some(c) = self.0.inlining_compiler() { c.finish_compiling(&mut body, None, symbol) .map_err(|e| CompileError::Codegen(e.to_string()))?; @@ -290,10 +313,10 @@ impl wasmtime_environ::Compiler for NoInlineCompiler { fn compile_wasm_to_builtin( &self, - index: BuiltinFunctionIndex, + key: FuncKey, symbol: &str, ) -> Result { - let mut body = self.0.compile_wasm_to_builtin(index, symbol)?; + let mut body = self.0.compile_wasm_to_builtin(key, symbol)?; if let Some(c) = self.0.inlining_compiler() { c.finish_compiling(&mut body, None, symbol) .map_err(|e| CompileError::Codegen(e.to_string()))?; @@ -304,7 +327,7 @@ impl wasmtime_environ::Compiler for NoInlineCompiler { fn compiled_function_relocation_targets<'a>( &'a self, func: &'a dyn Any, - ) -> Box + 'a> { + ) -> Box + 'a> { self.0.compiled_function_relocation_targets(func) } @@ -312,7 +335,7 @@ impl wasmtime_environ::Compiler for NoInlineCompiler { &self, obj: &mut Object<'static>, funcs: &[(String, Box)], - resolve_reloc: &dyn Fn(usize, RelocationTarget) -> usize, + resolve_reloc: &dyn Fn(usize, FuncKey) -> usize, ) -> Result> { self.0.append_code(obj, funcs, resolve_reloc) } @@ -360,14 +383,14 @@ impl wasmtime_environ::component::ComponentCompiler for NoInlineCompiler { &self, component: &wasmtime_environ::component::ComponentTranslation, types: &wasmtime_environ::component::ComponentTypesBuilder, - trampoline: wasmtime_environ::component::TrampolineIndex, + key: FuncKey, tunables: &Tunables, symbol: &str, ) -> Result> { let mut body = self .0 .component_compiler() - .compile_trampoline(component, types, trampoline, tunables, symbol)?; + .compile_trampoline(component, types, key, tunables, symbol)?; if let Some(c) = self.0.inlining_compiler() { c.finish_compiling(&mut body.array_call, None, symbol) .map_err(|e| CompileError::Codegen(e.to_string()))?; diff --git a/tests/disas/call-indirect.wat b/tests/disas/call-indirect.wat index 794e815cc..02b046ebf 100644 --- a/tests/disas/call-indirect.wat +++ b/tests/disas/call-indirect.wat @@ -16,7 +16,7 @@ ;; gv5 = load.i64 notrap aligned gv3+56 ;; sig0 = (i64 vmctx, i64, i32) -> i32 tail ;; sig1 = (i64 vmctx, i32, i64) -> i64 tail -;; fn0 = colocated u1:9 sig1 +;; fn0 = colocated u1610612736:9 sig1 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32): diff --git a/tests/disas/component-model/direct-adapter-calls-inlining.wat b/tests/disas/component-model/direct-adapter-calls-inlining.wat index ea078d34e..dab7c47b3 100644 --- a/tests/disas/component-model/direct-adapter-calls-inlining.wat +++ b/tests/disas/component-model/direct-adapter-calls-inlining.wat @@ -54,7 +54,7 @@ (export "g" (func $b "g")) ) -;; function u0:1(i64 vmctx, i64) -> i32 tail { +;; function u1:0(i64 vmctx, i64) -> i32 tail { ;; gv0 = vmctx ;; gv1 = load.i64 notrap aligned readonly gv0+8 ;; gv2 = load.i64 notrap aligned gv1+16 @@ -70,7 +70,7 @@ ;; gv12 = load.i64 notrap aligned gv11+16 ;; sig0 = (i64 vmctx, i64, i32) -> i32 tail ;; sig1 = (i64 vmctx, i64, i32) -> i32 tail -;; fn0 = colocated u0:0 sig0 +;; fn0 = colocated u2:0 sig0 ;; fn1 = colocated u0:0 sig1 ;; stack_limit = gv2 ;; diff --git a/tests/disas/component-model/direct-adapter-calls.wat b/tests/disas/component-model/direct-adapter-calls.wat index 52f88c625..c342cfd0f 100644 --- a/tests/disas/component-model/direct-adapter-calls.wat +++ b/tests/disas/component-model/direct-adapter-calls.wat @@ -72,13 +72,13 @@ ;; @003b return v5 ;; } ;; -;; function u0:1(i64 vmctx, i64) -> i32 tail { +;; function u1:0(i64 vmctx, i64) -> i32 tail { ;; gv0 = vmctx ;; gv1 = load.i64 notrap aligned readonly gv0+8 ;; gv2 = load.i64 notrap aligned gv1+16 ;; gv3 = vmctx ;; sig0 = (i64 vmctx, i64, i32) -> i32 tail -;; fn0 = colocated u0:0 sig0 +;; fn0 = colocated u2:0 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64): @@ -91,7 +91,7 @@ ;; @00f0 return v6 ;; } ;; -;; function u0:1(i64 vmctx, i64, i32) -> i32 tail { +;; function u2:0(i64 vmctx, i64, i32) -> i32 tail { ;; gv0 = vmctx ;; gv1 = load.i64 notrap aligned readonly gv0+8 ;; gv2 = load.i64 notrap aligned gv1+16 diff --git a/tests/disas/component-model/enum.wat b/tests/disas/component-model/enum.wat index 04b3bc2d2..e1ad99c9c 100644 --- a/tests/disas/component-model/enum.wat +++ b/tests/disas/component-model/enum.wat @@ -31,7 +31,7 @@ (with "f" (func $i1 "f")))) ) -;; function u0:1(i64 vmctx, i64) -> i32 tail { +;; function u2:0(i64 vmctx, i64) -> i32 tail { ;; gv0 = vmctx ;; gv1 = load.i64 notrap aligned readonly gv0+8 ;; gv2 = load.i64 notrap aligned gv1+16 diff --git a/tests/disas/component-model/exported-module-makes-adapters-indirect.wat b/tests/disas/component-model/exported-module-makes-adapters-indirect.wat index afc37dd44..603bd1f9a 100644 --- a/tests/disas/component-model/exported-module-makes-adapters-indirect.wat +++ b/tests/disas/component-model/exported-module-makes-adapters-indirect.wat @@ -58,7 +58,7 @@ (export "module" (core module $b "module")) ) -;; function u0:1(i64 vmctx, i64) -> i32 tail { +;; function u1:0(i64 vmctx, i64) -> i32 tail { ;; gv0 = vmctx ;; gv1 = load.i64 notrap aligned readonly gv0+8 ;; gv2 = load.i64 notrap aligned gv1+16 diff --git a/tests/disas/component-model/inlining-bug.wat b/tests/disas/component-model/inlining-bug.wat new file mode 100644 index 000000000..9c449eac0 --- /dev/null +++ b/tests/disas/component-model/inlining-bug.wat @@ -0,0 +1,93 @@ +;;! target = "x86_64" +;;! test = "optimize" +;;! filter = "wasm[2]--function" +;;! flags = "-C inlining=y" + +(component + (core module $A + (func (export "f0") (result i32) (i32.const 0)) + (func (export "f1") (result i32) (call $not-inlined) (i32.const 1)) + (func $not-inlined ) + ) + + (core module $B + (import "a" "f0" (func $f0 (result i32))) + (import "a" "f1" (func $f1 (result i32))) + (func (export "f2") (result i32) + (call $f1) + ) + ) + + (core module $C + (import "b" "f2" (func $f2 (result i32))) + (func (export "f3") (result i32) + (call $f2) + ) + ) + + (core instance $a (instantiate $A)) + (core instance $b (instantiate $B (with "a" (instance $a)))) + (core instance $c (instantiate $C (with "b" (instance $b)))) + + (func (export "f") (result u32) + (canon lift (core func $c "f3")) + ) +) + +;; function u2:0(i64 vmctx, i64) -> i32 tail { +;; gv0 = vmctx +;; gv1 = load.i64 notrap aligned readonly gv0+8 +;; gv2 = load.i64 notrap aligned gv1+16 +;; gv3 = vmctx +;; gv4 = vmctx +;; gv5 = load.i64 notrap aligned readonly gv4+8 +;; gv6 = load.i64 notrap aligned gv5+16 +;; gv7 = vmctx +;; gv8 = vmctx +;; gv9 = load.i64 notrap aligned readonly gv8+8 +;; gv10 = load.i64 notrap aligned gv9+16 +;; gv11 = vmctx +;; gv12 = load.i64 notrap aligned readonly gv11+8 +;; gv13 = load.i64 notrap aligned gv12+16 +;; sig0 = (i64 vmctx, i64) -> i32 tail +;; sig1 = (i64 vmctx, i64) -> i32 tail +;; sig2 = (i64 vmctx, i64) tail +;; fn0 = colocated u1:0 sig0 +;; fn1 = colocated u0:1 sig1 +;; fn2 = colocated u0:2 sig2 +;; stack_limit = gv2 +;; +;; block0(v0: i64, v1: i64): +;; @00d4 jump block2 +;; +;; block2: +;; jump block4 +;; +;; block4: +;; jump block7 +;; +;; block7: +;; jump block8 +;; +;; block8: +;; jump block9 +;; +;; block9: +;; jump block5 +;; +;; block5: +;; jump block6 +;; +;; block6: +;; jump block3 +;; +;; block3: +;; jump block10 +;; +;; block10: +;; @00d6 jump block1 +;; +;; block1: +;; v11 = iconst.i32 1 +;; @00d6 return v11 ; v11 = 1 +;; } diff --git a/tests/disas/component-model/inlining-fuzz-bug.wat b/tests/disas/component-model/inlining-fuzz-bug.wat index b62cd75aa..07278ac8f 100644 --- a/tests/disas/component-model/inlining-fuzz-bug.wat +++ b/tests/disas/component-model/inlining-fuzz-bug.wat @@ -37,7 +37,7 @@ ) ) -;; function u0:1(i64 vmctx, i64) -> i32 tail { +;; function u2:0(i64 vmctx, i64) -> i32 tail { ;; gv0 = vmctx ;; gv1 = load.i64 notrap aligned readonly gv0+8 ;; gv2 = load.i64 notrap aligned gv1+16 @@ -54,7 +54,7 @@ ;; gv13 = load.i64 notrap aligned gv12+16 ;; sig0 = (i64 vmctx, i64) -> i32 tail ;; sig1 = (i64 vmctx, i64) -> i32 tail -;; fn0 = colocated u0:0 sig0 +;; fn0 = colocated u1:0 sig0 ;; fn1 = colocated u0:0 sig1 ;; fn2 = colocated u0:1 sig1 ;; stack_limit = gv2 diff --git a/tests/disas/component-model/multiple-instantiations-makes-adapters-indirect.wat b/tests/disas/component-model/multiple-instantiations-makes-adapters-indirect.wat index 4d35c83a2..89f1871c8 100644 --- a/tests/disas/component-model/multiple-instantiations-makes-adapters-indirect.wat +++ b/tests/disas/component-model/multiple-instantiations-makes-adapters-indirect.wat @@ -64,7 +64,7 @@ (export "module" (core module $b "module")) ) -;; function u0:1(i64 vmctx, i64) -> i32 tail { +;; function u1:0(i64 vmctx, i64) -> i32 tail { ;; gv0 = vmctx ;; gv1 = load.i64 notrap aligned readonly gv0+8 ;; gv2 = load.i64 notrap aligned gv1+16 diff --git a/tests/disas/duplicate-function-types.wat b/tests/disas/duplicate-function-types.wat index 7f8e8206d..cf2139672 100644 --- a/tests/disas/duplicate-function-types.wat +++ b/tests/disas/duplicate-function-types.wat @@ -26,7 +26,7 @@ ;; gv6 = load.i64 notrap aligned gv4+8 ;; sig0 = (i64 vmctx, i64) -> i32 tail ;; sig1 = (i64 vmctx, i32, i64) -> i64 tail -;; fn0 = colocated u1:9 sig1 +;; fn0 = colocated u1610612736:9 sig1 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): diff --git a/tests/disas/epoch-interruption.wat b/tests/disas/epoch-interruption.wat index 8f09d34f1..f4dcffaa3 100644 --- a/tests/disas/epoch-interruption.wat +++ b/tests/disas/epoch-interruption.wat @@ -11,7 +11,7 @@ ;; gv3 = vmctx ;; gv4 = load.i64 notrap aligned readonly can_move gv3+8 ;; sig0 = (i64 vmctx) -> i64 tail -;; fn0 = colocated u1:16 sig0 +;; fn0 = colocated u1610612736:16 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64): diff --git a/tests/disas/gc/drc/array-new-fixed-of-gc-refs.wat b/tests/disas/gc/drc/array-new-fixed-of-gc-refs.wat index 1429607ee..4b224ed7c 100644 --- a/tests/disas/gc/drc/array-new-fixed-of-gc-refs.wat +++ b/tests/disas/gc/drc/array-new-fixed-of-gc-refs.wat @@ -21,7 +21,7 @@ ;; gv5 = load.i64 notrap aligned readonly can_move gv4+24 ;; gv6 = load.i64 notrap aligned gv4+32 ;; sig0 = (i64 vmctx, i32, i32, i32, i32) -> i32 tail -;; fn0 = colocated u1:27 sig0 +;; fn0 = colocated u1610612736:27 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32, v4: i32): diff --git a/tests/disas/gc/drc/array-new-fixed.wat b/tests/disas/gc/drc/array-new-fixed.wat index be8fe3776..6eac41958 100644 --- a/tests/disas/gc/drc/array-new-fixed.wat +++ b/tests/disas/gc/drc/array-new-fixed.wat @@ -17,7 +17,7 @@ ;; gv4 = load.i64 notrap aligned readonly can_move gv3+8 ;; gv5 = load.i64 notrap aligned readonly can_move gv4+24 ;; sig0 = (i64 vmctx, i32, i32, i32, i32) -> i32 tail -;; fn0 = colocated u1:27 sig0 +;; fn0 = colocated u1610612736:27 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i64, v3: i64, v4: i64): diff --git a/tests/disas/gc/drc/array-new.wat b/tests/disas/gc/drc/array-new.wat index a888392f4..d59c51d26 100644 --- a/tests/disas/gc/drc/array-new.wat +++ b/tests/disas/gc/drc/array-new.wat @@ -17,7 +17,7 @@ ;; gv4 = load.i64 notrap aligned readonly can_move gv3+8 ;; gv5 = load.i64 notrap aligned readonly can_move gv4+24 ;; sig0 = (i64 vmctx, i32, i32, i32, i32) -> i32 tail -;; fn0 = colocated u1:27 sig0 +;; fn0 = colocated u1610612736:27 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i64, v3: i32): diff --git a/tests/disas/gc/drc/br-on-cast-fail.wat b/tests/disas/gc/drc/br-on-cast-fail.wat index 1368346c7..6ca19404f 100644 --- a/tests/disas/gc/drc/br-on-cast-fail.wat +++ b/tests/disas/gc/drc/br-on-cast-fail.wat @@ -16,7 +16,7 @@ return ) ) -;; function u0:2(i64 vmctx, i64, i32) tail { +;; function u0:0(i64 vmctx, i64, i32) tail { ;; ss0 = explicit_slot 4, align = 4 ;; gv0 = vmctx ;; gv1 = load.i64 notrap aligned readonly gv0+8 @@ -27,7 +27,7 @@ ;; gv6 = load.i64 notrap aligned gv4+32 ;; sig0 = (i64 vmctx, i32, i32) -> i32 tail ;; sig1 = (i64 vmctx, i64) tail -;; fn0 = colocated u1:35 sig0 +;; fn0 = colocated u1610612736:35 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): diff --git a/tests/disas/gc/drc/br-on-cast.wat b/tests/disas/gc/drc/br-on-cast.wat index dff0153a7..7adb9bdf2 100644 --- a/tests/disas/gc/drc/br-on-cast.wat +++ b/tests/disas/gc/drc/br-on-cast.wat @@ -16,7 +16,7 @@ return ) ) -;; function u0:2(i64 vmctx, i64, i32) tail { +;; function u0:0(i64 vmctx, i64, i32) tail { ;; ss0 = explicit_slot 4, align = 4 ;; gv0 = vmctx ;; gv1 = load.i64 notrap aligned readonly gv0+8 @@ -27,7 +27,7 @@ ;; gv6 = load.i64 notrap aligned gv4+32 ;; sig0 = (i64 vmctx, i32, i32) -> i32 tail ;; sig1 = (i64 vmctx, i64) tail -;; fn0 = colocated u1:35 sig0 +;; fn0 = colocated u1610612736:35 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): diff --git a/tests/disas/gc/drc/call-indirect-and-subtyping.wat b/tests/disas/gc/drc/call-indirect-and-subtyping.wat index 200b8f566..9669191c5 100644 --- a/tests/disas/gc/drc/call-indirect-and-subtyping.wat +++ b/tests/disas/gc/drc/call-indirect-and-subtyping.wat @@ -16,7 +16,7 @@ (call_indirect (type $t1) (local.get 0)) ) ) -;; function u0:2(i64 vmctx, i64, i32) tail { +;; function u0:0(i64 vmctx, i64, i32) tail { ;; gv0 = vmctx ;; gv1 = load.i64 notrap aligned readonly gv0+8 ;; gv2 = load.i64 notrap aligned gv1+16 @@ -25,8 +25,8 @@ ;; sig0 = (i64 vmctx, i64) tail ;; sig1 = (i64 vmctx, i32, i64) -> i64 tail ;; sig2 = (i64 vmctx, i32, i32) -> i32 tail -;; fn0 = colocated u1:9 sig1 -;; fn1 = colocated u1:35 sig2 +;; fn0 = colocated u1610612736:9 sig1 +;; fn1 = colocated u1610612736:35 sig2 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): diff --git a/tests/disas/gc/drc/externref-globals.wat b/tests/disas/gc/drc/externref-globals.wat index 587d540c2..b878f0902 100644 --- a/tests/disas/gc/drc/externref-globals.wat +++ b/tests/disas/gc/drc/externref-globals.wat @@ -78,7 +78,7 @@ ;; gv5 = load.i64 notrap aligned readonly can_move gv4+24 ;; gv6 = load.i64 notrap aligned gv4+32 ;; sig0 = (i64 vmctx, i32) tail -;; fn0 = colocated u1:25 sig0 +;; fn0 = colocated u1610612736:25 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): diff --git a/tests/disas/gc/drc/funcref-in-gc-heap-get.wat b/tests/disas/gc/drc/funcref-in-gc-heap-get.wat index 32c65e647..226609b2e 100644 --- a/tests/disas/gc/drc/funcref-in-gc-heap-get.wat +++ b/tests/disas/gc/drc/funcref-in-gc-heap-get.wat @@ -18,7 +18,7 @@ ;; gv5 = load.i64 notrap aligned readonly can_move gv4+24 ;; gv6 = load.i64 notrap aligned gv4+32 ;; sig0 = (i64 vmctx, i32, i32) -> i64 tail -;; fn0 = colocated u1:29 sig0 +;; fn0 = colocated u1610612736:29 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): diff --git a/tests/disas/gc/drc/funcref-in-gc-heap-new.wat b/tests/disas/gc/drc/funcref-in-gc-heap-new.wat index 952acf538..87e548958 100644 --- a/tests/disas/gc/drc/funcref-in-gc-heap-new.wat +++ b/tests/disas/gc/drc/funcref-in-gc-heap-new.wat @@ -19,8 +19,8 @@ ;; gv5 = load.i64 notrap aligned readonly can_move gv4+24 ;; sig0 = (i64 vmctx, i32, i32, i32, i32) -> i32 tail ;; sig1 = (i64 vmctx, i64) -> i64 tail -;; fn0 = colocated u1:27 sig0 -;; fn1 = colocated u1:28 sig1 +;; fn0 = colocated u1610612736:27 sig0 +;; fn1 = colocated u1610612736:28 sig1 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i64): diff --git a/tests/disas/gc/drc/funcref-in-gc-heap-set.wat b/tests/disas/gc/drc/funcref-in-gc-heap-set.wat index db8dd8fe9..511596b09 100644 --- a/tests/disas/gc/drc/funcref-in-gc-heap-set.wat +++ b/tests/disas/gc/drc/funcref-in-gc-heap-set.wat @@ -18,7 +18,7 @@ ;; gv5 = load.i64 notrap aligned readonly can_move gv4+24 ;; gv6 = load.i64 notrap aligned gv4+32 ;; sig0 = (i64 vmctx, i64) -> i64 tail -;; fn0 = colocated u1:28 sig0 +;; fn0 = colocated u1610612736:28 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i64): diff --git a/tests/disas/gc/drc/ref-cast.wat b/tests/disas/gc/drc/ref-cast.wat index 6bea7387e..63d833f3f 100644 --- a/tests/disas/gc/drc/ref-cast.wat +++ b/tests/disas/gc/drc/ref-cast.wat @@ -18,7 +18,7 @@ ;; gv5 = load.i64 notrap aligned readonly can_move gv4+24 ;; gv6 = load.i64 notrap aligned gv4+32 ;; sig0 = (i64 vmctx, i32, i32) -> i32 tail -;; fn0 = colocated u1:35 sig0 +;; fn0 = colocated u1610612736:35 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): diff --git a/tests/disas/gc/drc/ref-test-concrete-func-type.wat b/tests/disas/gc/drc/ref-test-concrete-func-type.wat index 0bcb35bf3..b1a38fbb5 100644 --- a/tests/disas/gc/drc/ref-test-concrete-func-type.wat +++ b/tests/disas/gc/drc/ref-test-concrete-func-type.wat @@ -14,7 +14,7 @@ ;; gv2 = load.i64 notrap aligned gv1+16 ;; gv3 = vmctx ;; sig0 = (i64 vmctx, i32, i32) -> i32 tail -;; fn0 = colocated u1:35 sig0 +;; fn0 = colocated u1610612736:35 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i64): diff --git a/tests/disas/gc/drc/ref-test-concrete-type.wat b/tests/disas/gc/drc/ref-test-concrete-type.wat index da3b61f53..25f7897c7 100644 --- a/tests/disas/gc/drc/ref-test-concrete-type.wat +++ b/tests/disas/gc/drc/ref-test-concrete-type.wat @@ -17,7 +17,7 @@ ;; gv5 = load.i64 notrap aligned readonly can_move gv4+24 ;; gv6 = load.i64 notrap aligned gv4+32 ;; sig0 = (i64 vmctx, i32, i32) -> i32 tail -;; fn0 = colocated u1:35 sig0 +;; fn0 = colocated u1610612736:35 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): diff --git a/tests/disas/gc/drc/struct-new-default.wat b/tests/disas/gc/drc/struct-new-default.wat index b04f34436..feb660998 100644 --- a/tests/disas/gc/drc/struct-new-default.wat +++ b/tests/disas/gc/drc/struct-new-default.wat @@ -20,7 +20,7 @@ ;; gv5 = load.i64 notrap aligned readonly can_move gv4+24 ;; gv6 = load.i64 notrap aligned gv4+32 ;; sig0 = (i64 vmctx, i32, i32, i32, i32) -> i32 tail -;; fn0 = colocated u1:27 sig0 +;; fn0 = colocated u1610612736:27 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64): diff --git a/tests/disas/gc/drc/struct-new.wat b/tests/disas/gc/drc/struct-new.wat index f821ca8cb..c8ea45a89 100644 --- a/tests/disas/gc/drc/struct-new.wat +++ b/tests/disas/gc/drc/struct-new.wat @@ -21,7 +21,7 @@ ;; gv5 = load.i64 notrap aligned readonly can_move gv4+24 ;; gv6 = load.i64 notrap aligned gv4+32 ;; sig0 = (i64 vmctx, i32, i32, i32, i32) -> i32 tail -;; fn0 = colocated u1:27 sig0 +;; fn0 = colocated u1610612736:27 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: f32, v3: i32, v4: i32): diff --git a/tests/disas/gc/drc/struct-set.wat b/tests/disas/gc/drc/struct-set.wat index c4fd5e18e..109f0a837 100644 --- a/tests/disas/gc/drc/struct-set.wat +++ b/tests/disas/gc/drc/struct-set.wat @@ -78,7 +78,7 @@ ;; gv5 = load.i64 notrap aligned readonly can_move gv4+24 ;; gv6 = load.i64 notrap aligned gv4+32 ;; sig0 = (i64 vmctx, i32) tail -;; fn0 = colocated u1:25 sig0 +;; fn0 = colocated u1610612736:25 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32): diff --git a/tests/disas/gc/null/array-new-fixed-of-gc-refs.wat b/tests/disas/gc/null/array-new-fixed-of-gc-refs.wat index 12dd5fe01..963afecaf 100644 --- a/tests/disas/gc/null/array-new-fixed-of-gc-refs.wat +++ b/tests/disas/gc/null/array-new-fixed-of-gc-refs.wat @@ -21,7 +21,7 @@ ;; gv5 = load.i64 notrap aligned gv4+32 ;; gv6 = load.i64 notrap aligned readonly can_move gv4+24 ;; sig0 = (i64 vmctx, i64) -> i8 tail -;; fn0 = colocated u1:26 sig0 +;; fn0 = colocated u1610612736:26 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32, v4: i32): diff --git a/tests/disas/gc/null/array-new-fixed.wat b/tests/disas/gc/null/array-new-fixed.wat index e9a3fc08c..792803c24 100644 --- a/tests/disas/gc/null/array-new-fixed.wat +++ b/tests/disas/gc/null/array-new-fixed.wat @@ -18,7 +18,7 @@ ;; gv5 = load.i64 notrap aligned gv4+32 ;; gv6 = load.i64 notrap aligned readonly can_move gv4+24 ;; sig0 = (i64 vmctx, i64) -> i8 tail -;; fn0 = colocated u1:26 sig0 +;; fn0 = colocated u1610612736:26 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i64, v3: i64, v4: i64): diff --git a/tests/disas/gc/null/array-new.wat b/tests/disas/gc/null/array-new.wat index dc79a568c..9335a0478 100644 --- a/tests/disas/gc/null/array-new.wat +++ b/tests/disas/gc/null/array-new.wat @@ -18,7 +18,7 @@ ;; gv5 = load.i64 notrap aligned gv4+32 ;; gv6 = load.i64 notrap aligned readonly can_move gv4+24 ;; sig0 = (i64 vmctx, i64) -> i8 tail -;; fn0 = colocated u1:26 sig0 +;; fn0 = colocated u1610612736:26 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i64, v3: i32): diff --git a/tests/disas/gc/null/br-on-cast-fail.wat b/tests/disas/gc/null/br-on-cast-fail.wat index 5ef3653ae..e16a70c39 100644 --- a/tests/disas/gc/null/br-on-cast-fail.wat +++ b/tests/disas/gc/null/br-on-cast-fail.wat @@ -16,7 +16,7 @@ return ) ) -;; function u0:2(i64 vmctx, i64, i32) tail { +;; function u0:0(i64 vmctx, i64, i32) tail { ;; ss0 = explicit_slot 4, align = 4 ;; gv0 = vmctx ;; gv1 = load.i64 notrap aligned readonly gv0+8 @@ -27,7 +27,7 @@ ;; gv6 = load.i64 notrap aligned gv4+32 ;; sig0 = (i64 vmctx, i32, i32) -> i32 tail ;; sig1 = (i64 vmctx, i64) tail -;; fn0 = colocated u1:35 sig0 +;; fn0 = colocated u1610612736:35 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): diff --git a/tests/disas/gc/null/br-on-cast.wat b/tests/disas/gc/null/br-on-cast.wat index 27bf38f70..b8340d637 100644 --- a/tests/disas/gc/null/br-on-cast.wat +++ b/tests/disas/gc/null/br-on-cast.wat @@ -16,7 +16,7 @@ return ) ) -;; function u0:2(i64 vmctx, i64, i32) tail { +;; function u0:0(i64 vmctx, i64, i32) tail { ;; ss0 = explicit_slot 4, align = 4 ;; gv0 = vmctx ;; gv1 = load.i64 notrap aligned readonly gv0+8 @@ -27,7 +27,7 @@ ;; gv6 = load.i64 notrap aligned gv4+32 ;; sig0 = (i64 vmctx, i32, i32) -> i32 tail ;; sig1 = (i64 vmctx, i64) tail -;; fn0 = colocated u1:35 sig0 +;; fn0 = colocated u1610612736:35 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): diff --git a/tests/disas/gc/null/call-indirect-and-subtyping.wat b/tests/disas/gc/null/call-indirect-and-subtyping.wat index cfe055252..f1bff51d6 100644 --- a/tests/disas/gc/null/call-indirect-and-subtyping.wat +++ b/tests/disas/gc/null/call-indirect-and-subtyping.wat @@ -16,7 +16,7 @@ (call_indirect (type $t1) (local.get 0)) ) ) -;; function u0:2(i64 vmctx, i64, i32) tail { +;; function u0:0(i64 vmctx, i64, i32) tail { ;; gv0 = vmctx ;; gv1 = load.i64 notrap aligned readonly gv0+8 ;; gv2 = load.i64 notrap aligned gv1+16 @@ -25,8 +25,8 @@ ;; sig0 = (i64 vmctx, i64) tail ;; sig1 = (i64 vmctx, i32, i64) -> i64 tail ;; sig2 = (i64 vmctx, i32, i32) -> i32 tail -;; fn0 = colocated u1:9 sig1 -;; fn1 = colocated u1:35 sig2 +;; fn0 = colocated u1610612736:9 sig1 +;; fn1 = colocated u1610612736:35 sig2 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): diff --git a/tests/disas/gc/null/funcref-in-gc-heap-get.wat b/tests/disas/gc/null/funcref-in-gc-heap-get.wat index 558aa070e..a12beba91 100644 --- a/tests/disas/gc/null/funcref-in-gc-heap-get.wat +++ b/tests/disas/gc/null/funcref-in-gc-heap-get.wat @@ -18,7 +18,7 @@ ;; gv5 = load.i64 notrap aligned readonly can_move gv4+24 ;; gv6 = load.i64 notrap aligned gv4+32 ;; sig0 = (i64 vmctx, i32, i32) -> i64 tail -;; fn0 = colocated u1:29 sig0 +;; fn0 = colocated u1610612736:29 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): diff --git a/tests/disas/gc/null/funcref-in-gc-heap-new.wat b/tests/disas/gc/null/funcref-in-gc-heap-new.wat index 90401943f..658c4d833 100644 --- a/tests/disas/gc/null/funcref-in-gc-heap-new.wat +++ b/tests/disas/gc/null/funcref-in-gc-heap-new.wat @@ -19,8 +19,8 @@ ;; gv6 = load.i64 notrap aligned readonly can_move gv4+24 ;; sig0 = (i64 vmctx, i64) -> i8 tail ;; sig1 = (i64 vmctx, i64) -> i64 tail -;; fn0 = colocated u1:26 sig0 -;; fn1 = colocated u1:28 sig1 +;; fn0 = colocated u1610612736:26 sig0 +;; fn1 = colocated u1610612736:28 sig1 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i64): diff --git a/tests/disas/gc/null/funcref-in-gc-heap-set.wat b/tests/disas/gc/null/funcref-in-gc-heap-set.wat index 687da61ce..97dba164e 100644 --- a/tests/disas/gc/null/funcref-in-gc-heap-set.wat +++ b/tests/disas/gc/null/funcref-in-gc-heap-set.wat @@ -18,7 +18,7 @@ ;; gv5 = load.i64 notrap aligned readonly can_move gv4+24 ;; gv6 = load.i64 notrap aligned gv4+32 ;; sig0 = (i64 vmctx, i64) -> i64 tail -;; fn0 = colocated u1:28 sig0 +;; fn0 = colocated u1610612736:28 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i64): diff --git a/tests/disas/gc/null/ref-cast.wat b/tests/disas/gc/null/ref-cast.wat index 4788cd5f2..451898878 100644 --- a/tests/disas/gc/null/ref-cast.wat +++ b/tests/disas/gc/null/ref-cast.wat @@ -18,7 +18,7 @@ ;; gv5 = load.i64 notrap aligned readonly can_move gv4+24 ;; gv6 = load.i64 notrap aligned gv4+32 ;; sig0 = (i64 vmctx, i32, i32) -> i32 tail -;; fn0 = colocated u1:35 sig0 +;; fn0 = colocated u1610612736:35 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): diff --git a/tests/disas/gc/null/ref-test-concrete-func-type.wat b/tests/disas/gc/null/ref-test-concrete-func-type.wat index bcc6d606b..30b06b480 100644 --- a/tests/disas/gc/null/ref-test-concrete-func-type.wat +++ b/tests/disas/gc/null/ref-test-concrete-func-type.wat @@ -14,7 +14,7 @@ ;; gv2 = load.i64 notrap aligned gv1+16 ;; gv3 = vmctx ;; sig0 = (i64 vmctx, i32, i32) -> i32 tail -;; fn0 = colocated u1:35 sig0 +;; fn0 = colocated u1610612736:35 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i64): diff --git a/tests/disas/gc/null/ref-test-concrete-type.wat b/tests/disas/gc/null/ref-test-concrete-type.wat index 673e890dd..89809a375 100644 --- a/tests/disas/gc/null/ref-test-concrete-type.wat +++ b/tests/disas/gc/null/ref-test-concrete-type.wat @@ -17,7 +17,7 @@ ;; gv5 = load.i64 notrap aligned readonly can_move gv4+24 ;; gv6 = load.i64 notrap aligned gv4+32 ;; sig0 = (i64 vmctx, i32, i32) -> i32 tail -;; fn0 = colocated u1:35 sig0 +;; fn0 = colocated u1610612736:35 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): diff --git a/tests/disas/gc/null/struct-new-default.wat b/tests/disas/gc/null/struct-new-default.wat index 957895c92..c67db4ca4 100644 --- a/tests/disas/gc/null/struct-new-default.wat +++ b/tests/disas/gc/null/struct-new-default.wat @@ -20,7 +20,7 @@ ;; gv5 = load.i64 notrap aligned gv4+32 ;; gv6 = load.i64 notrap aligned readonly can_move gv4+24 ;; sig0 = (i64 vmctx, i64) -> i8 tail -;; fn0 = colocated u1:26 sig0 +;; fn0 = colocated u1610612736:26 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64): diff --git a/tests/disas/gc/null/struct-new.wat b/tests/disas/gc/null/struct-new.wat index 247786227..36b5e1ad2 100644 --- a/tests/disas/gc/null/struct-new.wat +++ b/tests/disas/gc/null/struct-new.wat @@ -21,7 +21,7 @@ ;; gv5 = load.i64 notrap aligned gv4+32 ;; gv6 = load.i64 notrap aligned readonly can_move gv4+24 ;; sig0 = (i64 vmctx, i64) -> i8 tail -;; fn0 = colocated u1:26 sig0 +;; fn0 = colocated u1610612736:26 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: f32, v3: i32, v4: i32): diff --git a/tests/disas/gc/struct-new-default.wat b/tests/disas/gc/struct-new-default.wat index 75416dd00..3141cfb7d 100644 --- a/tests/disas/gc/struct-new-default.wat +++ b/tests/disas/gc/struct-new-default.wat @@ -21,7 +21,7 @@ ;; gv5 = load.i64 notrap aligned readonly can_move gv4+24 ;; gv6 = load.i64 notrap aligned gv4+32 ;; sig0 = (i64 vmctx, i32, i32, i32, i32) -> i32 tail -;; fn0 = colocated u1:27 sig0 +;; fn0 = colocated u1610612736:27 sig0 ;; const0 = 0x00000000000000000000000000000000 ;; stack_limit = gv2 ;; diff --git a/tests/disas/gc/struct-new.wat b/tests/disas/gc/struct-new.wat index 9756c7bff..7f59fc129 100644 --- a/tests/disas/gc/struct-new.wat +++ b/tests/disas/gc/struct-new.wat @@ -21,7 +21,7 @@ ;; gv5 = load.i64 notrap aligned readonly can_move gv4+24 ;; gv6 = load.i64 notrap aligned gv4+32 ;; sig0 = (i64 vmctx, i32, i32, i32, i32) -> i32 tail -;; fn0 = colocated u1:27 sig0 +;; fn0 = colocated u1610612736:27 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: f32, v3: i32, v4: i32): diff --git a/tests/disas/icall-loop.wat b/tests/disas/icall-loop.wat index 8107c3d71..ac63bc9be 100644 --- a/tests/disas/icall-loop.wat +++ b/tests/disas/icall-loop.wat @@ -30,7 +30,7 @@ ;; gv4 = load.i64 notrap aligned readonly can_move gv3+48 ;; sig0 = (i64 vmctx, i64) -> i32 tail ;; sig1 = (i64 vmctx, i32, i64) -> i64 tail -;; fn0 = colocated u1:9 sig1 +;; fn0 = colocated u1610612736:9 sig1 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): @@ -78,7 +78,7 @@ ;; gv4 = load.i64 notrap aligned readonly can_move gv3+48 ;; sig0 = (i64 vmctx, i64) -> i32 tail ;; sig1 = (i64 vmctx, i32, i64) -> i64 tail -;; fn0 = colocated u1:9 sig1 +;; fn0 = colocated u1610612736:9 sig1 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64): diff --git a/tests/disas/icall-simd.wat b/tests/disas/icall-simd.wat index 64f0d37c1..6733afce4 100644 --- a/tests/disas/icall-simd.wat +++ b/tests/disas/icall-simd.wat @@ -16,7 +16,7 @@ ;; gv4 = load.i64 notrap aligned readonly can_move gv3+48 ;; sig0 = (i64 vmctx, i64, i8x16) -> i8x16 tail ;; sig1 = (i64 vmctx, i32, i64) -> i64 tail -;; fn0 = colocated u1:9 sig1 +;; fn0 = colocated u1610612736:9 sig1 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i8x16): diff --git a/tests/disas/icall.wat b/tests/disas/icall.wat index d3df0defb..aeb4cb467 100644 --- a/tests/disas/icall.wat +++ b/tests/disas/icall.wat @@ -16,7 +16,7 @@ ;; gv4 = load.i64 notrap aligned readonly can_move gv3+48 ;; sig0 = (i64 vmctx, i64, f32) -> i32 tail ;; sig1 = (i64 vmctx, i32, i64) -> i64 tail -;; fn0 = colocated u1:9 sig1 +;; fn0 = colocated u1610612736:9 sig1 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: f32): diff --git a/tests/disas/indirect-call-no-caching.wat b/tests/disas/indirect-call-no-caching.wat index 41061d121..a30b25af5 100644 --- a/tests/disas/indirect-call-no-caching.wat +++ b/tests/disas/indirect-call-no-caching.wat @@ -70,7 +70,7 @@ ;; gv4 = load.i64 notrap aligned readonly can_move gv3+48 ;; sig0 = (i64 vmctx, i64) -> i32 tail ;; sig1 = (i64 vmctx, i32, i64) -> i64 tail -;; fn0 = colocated u1:9 sig1 +;; fn0 = colocated u1610612736:9 sig1 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): diff --git a/tests/disas/memory-min-max-same.wat b/tests/disas/memory-min-max-same.wat index 92b80e5c5..75d433e74 100644 --- a/tests/disas/memory-min-max-same.wat +++ b/tests/disas/memory-min-max-same.wat @@ -33,7 +33,7 @@ ) ) ) -;; function u0:1(i64 vmctx, i64, i32) tail { +;; function u0:0(i64 vmctx, i64, i32) tail { ;; gv0 = vmctx ;; gv1 = load.i64 notrap aligned readonly gv0+8 ;; gv2 = load.i64 notrap aligned gv1+16 diff --git a/tests/disas/passive-data.wat b/tests/disas/passive-data.wat index d03facda0..21de22f46 100644 --- a/tests/disas/passive-data.wat +++ b/tests/disas/passive-data.wat @@ -21,7 +21,7 @@ ;; gv4 = load.i64 notrap aligned gv3+64 ;; gv5 = load.i64 notrap aligned readonly can_move checked gv3+56 ;; sig0 = (i64 vmctx, i32, i32, i64, i32, i32) -> i8 tail -;; fn0 = colocated u1:6 sig0 +;; fn0 = colocated u1610612736:6 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32, v4: i32): @@ -41,7 +41,7 @@ ;; gv2 = load.i64 notrap aligned gv1+16 ;; gv3 = vmctx ;; sig0 = (i64 vmctx, i32) tail -;; fn0 = colocated u1:8 sig0 +;; fn0 = colocated u1610612736:8 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64): diff --git a/tests/disas/readonly-funcrefs.wat b/tests/disas/readonly-funcrefs.wat index db3c160bc..6091c33e9 100644 --- a/tests/disas/readonly-funcrefs.wat +++ b/tests/disas/readonly-funcrefs.wat @@ -39,7 +39,7 @@ ;; gv4 = load.i64 notrap aligned readonly can_move gv3+48 ;; sig0 = (i64 vmctx, i64) tail ;; sig1 = (i64 vmctx, i32, i64) -> i64 tail -;; fn0 = colocated u1:9 sig1 +;; fn0 = colocated u1610612736:9 sig1 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): diff --git a/tests/disas/ref-func-0.wat b/tests/disas/ref-func-0.wat index c87baad71..8ebbadbf7 100644 --- a/tests/disas/ref-func-0.wat +++ b/tests/disas/ref-func-0.wat @@ -13,7 +13,7 @@ (global (export "funcref-imported") funcref (ref.func $imported)) (global (export "funcref-local") funcref (ref.func $local))) -;; function u0:1(i64 vmctx, i64) -> i32, i32, i64, i64 tail { +;; function u0:0(i64 vmctx, i64) -> i32, i32, i64, i64 tail { ;; gv0 = vmctx ;; gv1 = load.i64 notrap aligned readonly gv0+8 ;; gv2 = load.i64 notrap aligned gv1+16 diff --git a/tests/disas/table-copy.wat b/tests/disas/table-copy.wat index 718f71168..05d8fcde4 100644 --- a/tests/disas/table-copy.wat +++ b/tests/disas/table-copy.wat @@ -68,7 +68,7 @@ ;; gv2 = load.i64 notrap aligned gv1+16 ;; gv3 = vmctx ;; sig0 = (i64 vmctx, i32, i32, i64, i64, i64) -> i8 tail -;; fn0 = colocated u1:1 sig0 +;; fn0 = colocated u1610612736:1 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32, v4: i32, v5: i32): @@ -90,7 +90,7 @@ ;; gv2 = load.i64 notrap aligned gv1+16 ;; gv3 = vmctx ;; sig0 = (i64 vmctx, i32, i32, i64, i64, i64) -> i8 tail -;; fn0 = colocated u1:1 sig0 +;; fn0 = colocated u1610612736:1 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32, v4: i32, v5: i32): diff --git a/tests/disas/table-set-fixed-size.wat b/tests/disas/table-set-fixed-size.wat index de94d4748..86e57ff33 100644 --- a/tests/disas/table-set-fixed-size.wat +++ b/tests/disas/table-set-fixed-size.wat @@ -26,7 +26,7 @@ ;; gv6 = load.i64 notrap aligned readonly can_move gv5+24 ;; gv7 = load.i64 notrap aligned gv5+32 ;; sig0 = (i64 vmctx, i32) tail -;; fn0 = colocated u1:25 sig0 +;; fn0 = colocated u1610612736:25 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): @@ -123,7 +123,7 @@ ;; gv6 = load.i64 notrap aligned readonly can_move gv5+24 ;; gv7 = load.i64 notrap aligned gv5+32 ;; sig0 = (i64 vmctx, i32) tail -;; fn0 = colocated u1:25 sig0 +;; fn0 = colocated u1610612736:25 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32): diff --git a/tests/disas/table-set.wat b/tests/disas/table-set.wat index b09422f78..ee30fbc37 100644 --- a/tests/disas/table-set.wat +++ b/tests/disas/table-set.wat @@ -27,7 +27,7 @@ ;; gv7 = load.i64 notrap aligned readonly can_move gv6+24 ;; gv8 = load.i64 notrap aligned gv6+32 ;; sig0 = (i64 vmctx, i32) tail -;; fn0 = colocated u1:25 sig0 +;; fn0 = colocated u1610612736:25 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32): @@ -126,7 +126,7 @@ ;; gv7 = load.i64 notrap aligned readonly can_move gv6+24 ;; gv8 = load.i64 notrap aligned gv6+32 ;; sig0 = (i64 vmctx, i32) tail -;; fn0 = colocated u1:25 sig0 +;; fn0 = colocated u1610612736:25 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32): diff --git a/tests/disas/typed-funcrefs.wat b/tests/disas/typed-funcrefs.wat index 23e3545ba..310334996 100644 --- a/tests/disas/typed-funcrefs.wat +++ b/tests/disas/typed-funcrefs.wat @@ -134,7 +134,7 @@ ;; gv4 = load.i64 notrap aligned readonly can_move gv3+48 ;; sig0 = (i64 vmctx, i32, i64) -> i64 tail ;; sig1 = (i64 vmctx, i64, i32, i32, i32, i32) -> i32 tail -;; fn0 = colocated u1:9 sig0 +;; fn0 = colocated u1610612736:9 sig0 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32, v4: i32, v5: i32): @@ -188,7 +188,7 @@ ;; gv4 = load.i64 notrap aligned readonly can_move gv3+48 ;; sig0 = (i64 vmctx, i64, i32, i32, i32, i32) -> i32 tail ;; sig1 = (i64 vmctx, i32, i64) -> i64 tail -;; fn0 = colocated u1:9 sig1 +;; fn0 = colocated u1610612736:9 sig1 ;; stack_limit = gv2 ;; ;; block0(v0: i64, v1: i64, v2: i32, v3: i32, v4: i32, v5: i32): diff --git a/tests/disas/winch/x64/table/init_copy_drop.wat b/tests/disas/winch/x64/table/init_copy_drop.wat index b753b658d..138863dea 100644 --- a/tests/disas/winch/x64/table/init_copy_drop.wat +++ b/tests/disas/winch/x64/table/init_copy_drop.wat @@ -142,11 +142,11 @@ ;; movl $7, %ecx ;; movl $0, %r8d ;; movl $4, %r9d -;; callq 0x8a7 +;; callq 0x905 ;; movq 8(%rsp), %r14 ;; movq %r14, %rdi ;; movl $1, %esi -;; callq 0x905 +;; callq 0x963 ;; movq 8(%rsp), %r14 ;; movq %r14, %rdi ;; movl $0, %esi @@ -154,11 +154,11 @@ ;; movl $0xf, %ecx ;; movl $1, %r8d ;; movl $3, %r9d -;; callq 0x8a7 +;; callq 0x905 ;; movq 8(%rsp), %r14 ;; movq %r14, %rdi ;; movl $3, %esi -;; callq 0x905 +;; callq 0x963 ;; movq 8(%rsp), %r14 ;; movq %r14, %rdi ;; movl $0, %esi @@ -166,7 +166,7 @@ ;; movl $0x14, %ecx ;; movl $0xf, %r8d ;; movl $5, %r9d -;; callq 0x943 +;; callq 0x8a7 ;; movq 8(%rsp), %r14 ;; movq %r14, %rdi ;; movl $0, %esi @@ -174,7 +174,7 @@ ;; movl $0x15, %ecx ;; movl $0x1d, %r8d ;; movl $1, %r9d -;; callq 0x943 +;; callq 0x8a7 ;; movq 8(%rsp), %r14 ;; movq %r14, %rdi ;; movl $0, %esi @@ -182,7 +182,7 @@ ;; movl $0x18, %ecx ;; movl $0xa, %r8d ;; movl $1, %r9d -;; callq 0x943 +;; callq 0x8a7 ;; movq 8(%rsp), %r14 ;; movq %r14, %rdi ;; movl $0, %esi @@ -190,7 +190,7 @@ ;; movl $0xd, %ecx ;; movl $0xb, %r8d ;; movl $4, %r9d -;; callq 0x943 +;; callq 0x8a7 ;; movq 8(%rsp), %r14 ;; movq %r14, %rdi ;; movl $0, %esi @@ -198,7 +198,7 @@ ;; movl $0x13, %ecx ;; movl $0x14, %r8d ;; movl $5, %r9d -;; callq 0x943 +;; callq 0x8a7 ;; movq 8(%rsp), %r14 ;; addq $0x10, %rsp ;; popq %rbp diff --git a/tests/disas/x64-simd-round-without-sse41.wat b/tests/disas/x64-simd-round-without-sse41.wat index 197bce1b2..c3dd36b46 100644 --- a/tests/disas/x64-simd-round-without-sse41.wat +++ b/tests/disas/x64-simd-round-without-sse41.wat @@ -17,7 +17,7 @@ ;; gv2 = load.i64 notrap aligned gv1+16 ;; gv3 = vmctx ;; sig0 = (i64 vmctx, f32) -> f32 tail -;; fn0 = colocated u1:38 sig0 +;; fn0 = colocated u1610612736:38 sig0 ;; const0 = 0x00000000000000000000000000000000 ;; stack_limit = gv2 ;; @@ -49,7 +49,7 @@ ;; gv2 = load.i64 notrap aligned gv1+16 ;; gv3 = vmctx ;; sig0 = (i64 vmctx, f32) -> f32 tail -;; fn0 = colocated u1:40 sig0 +;; fn0 = colocated u1610612736:40 sig0 ;; const0 = 0x00000000000000000000000000000000 ;; stack_limit = gv2 ;; @@ -81,7 +81,7 @@ ;; gv2 = load.i64 notrap aligned gv1+16 ;; gv3 = vmctx ;; sig0 = (i64 vmctx, f32) -> f32 tail -;; fn0 = colocated u1:42 sig0 +;; fn0 = colocated u1610612736:42 sig0 ;; const0 = 0x00000000000000000000000000000000 ;; stack_limit = gv2 ;; @@ -113,7 +113,7 @@ ;; gv2 = load.i64 notrap aligned gv1+16 ;; gv3 = vmctx ;; sig0 = (i64 vmctx, f32) -> f32 tail -;; fn0 = colocated u1:44 sig0 +;; fn0 = colocated u1610612736:44 sig0 ;; const0 = 0x00000000000000000000000000000000 ;; stack_limit = gv2 ;; @@ -145,7 +145,7 @@ ;; gv2 = load.i64 notrap aligned gv1+16 ;; gv3 = vmctx ;; sig0 = (i64 vmctx, f64) -> f64 tail -;; fn0 = colocated u1:39 sig0 +;; fn0 = colocated u1610612736:39 sig0 ;; const0 = 0x00000000000000000000000000000000 ;; stack_limit = gv2 ;; @@ -171,7 +171,7 @@ ;; gv2 = load.i64 notrap aligned gv1+16 ;; gv3 = vmctx ;; sig0 = (i64 vmctx, f64) -> f64 tail -;; fn0 = colocated u1:41 sig0 +;; fn0 = colocated u1610612736:41 sig0 ;; const0 = 0x00000000000000000000000000000000 ;; stack_limit = gv2 ;; @@ -197,7 +197,7 @@ ;; gv2 = load.i64 notrap aligned gv1+16 ;; gv3 = vmctx ;; sig0 = (i64 vmctx, f64) -> f64 tail -;; fn0 = colocated u1:43 sig0 +;; fn0 = colocated u1610612736:43 sig0 ;; const0 = 0x00000000000000000000000000000000 ;; stack_limit = gv2 ;; @@ -223,7 +223,7 @@ ;; gv2 = load.i64 notrap aligned gv1+16 ;; gv3 = vmctx ;; sig0 = (i64 vmctx, f64) -> f64 tail -;; fn0 = colocated u1:45 sig0 +;; fn0 = colocated u1610612736:45 sig0 ;; const0 = 0x00000000000000000000000000000000 ;; stack_limit = gv2 ;; diff --git a/winch/codegen/src/codegen/call.rs b/winch/codegen/src/codegen/call.rs index 2f09c6b3e..43c544d78 100644 --- a/winch/codegen/src/codegen/call.rs +++ b/winch/codegen/src/codegen/call.rs @@ -70,7 +70,7 @@ use crate::{ stack::Val, }; use anyhow::{Result, ensure}; -use wasmtime_environ::{FuncIndex, PtrSize, VMOffsets}; +use wasmtime_environ::{DefinedFuncIndex, FuncIndex, PtrSize, VMOffsets}; /// All the information needed to emit a function call. #[derive(Copy, Clone)] @@ -148,7 +148,10 @@ impl FnCall { Callee::FuncRef(_) => { Self::lower_funcref(env.callee_sig::(callee)?, ptr, context, masm) } - Callee::Local(i) => Ok(Self::lower_local(env, *i)), + Callee::Local(i) => { + let f = env.translation.module.defined_func_index(*i).unwrap(); + Ok(Self::lower_local(env, f)) + } Callee::Import(i) => { let sig = env.callee_sig::(callee)?; Self::lower_import(*i, sig, context, masm, vmoffsets) @@ -177,7 +180,7 @@ impl FnCall { /// Lower a local function to a [`CalleeKind`] and [ContextArgs] pair. fn lower_local( env: &mut FuncEnv

, - index: FuncIndex, + index: DefinedFuncIndex, ) -> (CalleeKind, ContextArgs) { ( CalleeKind::direct(env.name_wasm(index)), diff --git a/winch/codegen/src/codegen/env.rs b/winch/codegen/src/codegen/env.rs index b58fb03a6..9f1b5e9ef 100644 --- a/winch/codegen/src/codegen/env.rs +++ b/winch/codegen/src/codegen/env.rs @@ -12,9 +12,9 @@ use std::collections::{ use std::mem; use wasmparser::BlockType; use wasmtime_environ::{ - BuiltinFunctionIndex, FuncIndex, GlobalIndex, IndexType, Memory, MemoryIndex, - ModuleTranslation, ModuleTypesBuilder, PrimaryMap, PtrSize, Table, TableIndex, TypeConvert, - TypeIndex, VMOffsets, WasmHeapType, WasmValType, + BuiltinFunctionIndex, DefinedFuncIndex, FuncIndex, FuncKey, GlobalIndex, IndexType, Memory, + MemoryIndex, ModuleTranslation, ModuleTypesBuilder, PrimaryMap, PtrSize, Table, TableIndex, + TypeConvert, TypeIndex, VMOffsets, WasmHeapType, WasmValType, }; #[derive(Debug, Clone, Copy)] @@ -354,18 +354,16 @@ impl<'a, 'translation, 'data, P: PtrSize> FuncEnv<'a, 'translation, 'data, P> { /// Creates a name to reference the `builtin` provided. pub fn name_builtin(&mut self, builtin: BuiltinFunctionIndex) -> UserExternalNameRef { - self.intern_name(UserExternalName { - namespace: wasmtime_cranelift::NS_WASMTIME_BUILTIN, - index: builtin.index(), - }) + let key = FuncKey::WasmToBuiltinTrampoline(builtin); + let (namespace, index) = key.into_raw_parts(); + self.intern_name(UserExternalName { namespace, index }) } /// Creates a name to reference the wasm function `index` provided. - pub fn name_wasm(&mut self, index: FuncIndex) -> UserExternalNameRef { - self.intern_name(UserExternalName { - namespace: wasmtime_cranelift::NS_WASM_FUNC, - index: index.as_u32(), - }) + pub fn name_wasm(&mut self, def_func: DefinedFuncIndex) -> UserExternalNameRef { + let key = FuncKey::DefinedWasmFunction(self.translation.module_index, def_func); + let (namespace, index) = key.into_raw_parts(); + self.intern_name(UserExternalName { namespace, index }) } /// Interns `name` into a `UserExternalNameRef` and ensures that duplicate