Path: blob/main/crates/environ/src/compile/key.rs
1693 views
//! Keys for identifying functions during compilation, in call graphs, and when1//! resolving relocations.23#[cfg(feature = "component-model")]4use crate::component;5use crate::{6BuiltinFunctionIndex, DefinedFuncIndex, HostCall, ModuleInternedTypeIndex, StaticModuleIndex,7};89/// A sortable, comparable function key for compilation output, call graph10/// edges, and relocations.11#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]12pub enum FuncKey {13/// A Wasm-defined function.14DefinedWasmFunction(StaticModuleIndex, DefinedFuncIndex),1516/// A trampoline from an array-caller to the given Wasm-callee.17ArrayToWasmTrampoline(StaticModuleIndex, DefinedFuncIndex),1819/// A trampoline from a Wasm-caller to an array-callee of the given type.20WasmToArrayTrampoline(ModuleInternedTypeIndex),2122/// A trampoline from a Wasm-caller to the given builtin.23WasmToBuiltinTrampoline(BuiltinFunctionIndex),2425/// A Pulley-specific host call.26PulleyHostCall(HostCall),2728/// A Wasm-caller to component builtin trampoline.29#[cfg(feature = "component-model")]30ComponentTrampoline(component::TrampolineIndex),3132/// A Wasm-caller to array-callee `resource.drop` trampoline.33#[cfg(feature = "component-model")]34ResourceDropTrampoline,35}3637impl FuncKey {38const KIND_BITS: u32 = 3;39const KIND_OFFSET: u32 = 32 - Self::KIND_BITS;40const KIND_MASK: u32 = ((1 << Self::KIND_BITS) - 1) << Self::KIND_OFFSET;41const MODULE_MASK: u32 = !Self::KIND_MASK;4243const fn new_kind(kind: u32) -> u32 {44assert!(kind < (1 << Self::KIND_BITS));45kind << Self::KIND_OFFSET46}4748const DEFINED_WASM_FUNCTION_KIND: u32 = Self::new_kind(0);49const ARRAY_TO_WASM_TRAMPOLINE_KIND: u32 = Self::new_kind(1);50const WASM_TO_ARRAY_TRAMPOLINE_KIND: u32 = Self::new_kind(2);51const WASM_TO_BUILTIN_TRAMPOLINE_KIND: u32 = Self::new_kind(3);52const PULLEY_HOST_CALL_KIND: u32 = Self::new_kind(4);5354#[cfg(feature = "component-model")]55const COMPONENT_TRAMPOLINE_KIND: u32 = Self::new_kind(5);56#[cfg(feature = "component-model")]57const RESOURCE_DROP_TRAMPOLINE_KIND: u32 = Self::new_kind(6);5859/// Get the raw, underlying representation of this compilation key.60///61/// The resulting values should only be used for (eventually) calling62/// `CompileKey::from_raw_parts`.63//64// NB: We use two `u32`s to exactly match65// `cranelift_codegen::ir::UserExternalName` and ensure that we can map66// one-to-one between that and `FuncKey`.67pub fn into_raw_parts(self) -> (u32, u32) {68match self {69FuncKey::DefinedWasmFunction(module, def_func) => {70assert_eq!(module.as_u32() & Self::KIND_MASK, 0);71let namespace = Self::DEFINED_WASM_FUNCTION_KIND | module.as_u32();72let index = def_func.as_u32();73(namespace, index)74}75FuncKey::ArrayToWasmTrampoline(module, def_func) => {76assert_eq!(module.as_u32() & Self::KIND_MASK, 0);77let namespace = Self::ARRAY_TO_WASM_TRAMPOLINE_KIND | module.as_u32();78let index = def_func.as_u32();79(namespace, index)80}81FuncKey::WasmToArrayTrampoline(ty) => {82let namespace = Self::WASM_TO_ARRAY_TRAMPOLINE_KIND;83let index = ty.as_u32();84(namespace, index)85}86FuncKey::WasmToBuiltinTrampoline(builtin) => {87let namespace = Self::WASM_TO_BUILTIN_TRAMPOLINE_KIND;88let index = builtin.index();89(namespace, index)90}91FuncKey::PulleyHostCall(host_call) => {92let namespace = Self::PULLEY_HOST_CALL_KIND;93let index = host_call.index();94(namespace, index)95}9697#[cfg(feature = "component-model")]98FuncKey::ComponentTrampoline(trampoline) => {99let namespace = Self::COMPONENT_TRAMPOLINE_KIND;100let index = trampoline.as_u32();101(namespace, index)102}103#[cfg(feature = "component-model")]104FuncKey::ResourceDropTrampoline => {105let namespace = Self::RESOURCE_DROP_TRAMPOLINE_KIND;106let index = 0;107(namespace, index)108}109}110}111112/// Create a compilation key from its raw, underlying representation.113///114/// Should only be given the results of a previous call to115/// `CompileKey::into_raw_parts`.116pub fn from_raw_parts(a: u32, b: u32) -> Self {117match a & Self::KIND_MASK {118Self::DEFINED_WASM_FUNCTION_KIND => {119let module = StaticModuleIndex::from_u32(a & Self::MODULE_MASK);120let def_func = DefinedFuncIndex::from_u32(b);121Self::DefinedWasmFunction(module, def_func)122}123Self::ARRAY_TO_WASM_TRAMPOLINE_KIND => {124let module = StaticModuleIndex::from_u32(a & Self::MODULE_MASK);125let def_func = DefinedFuncIndex::from_u32(b);126Self::ArrayToWasmTrampoline(module, def_func)127}128Self::WASM_TO_ARRAY_TRAMPOLINE_KIND => {129assert_eq!(a & Self::MODULE_MASK, 0);130let ty = ModuleInternedTypeIndex::from_u32(b);131Self::WasmToArrayTrampoline(ty)132}133Self::WASM_TO_BUILTIN_TRAMPOLINE_KIND => {134assert_eq!(a & Self::MODULE_MASK, 0);135let builtin = BuiltinFunctionIndex::from_u32(b);136Self::WasmToBuiltinTrampoline(builtin)137}138Self::PULLEY_HOST_CALL_KIND => {139assert_eq!(a & Self::MODULE_MASK, 0);140let host_call = HostCall::from_index(b);141Self::PulleyHostCall(host_call)142}143144#[cfg(feature = "component-model")]145Self::COMPONENT_TRAMPOLINE_KIND => {146assert_eq!(a & Self::MODULE_MASK, 0);147let trampoline = component::TrampolineIndex::from_u32(b);148Self::ComponentTrampoline(trampoline)149}150#[cfg(feature = "component-model")]151Self::RESOURCE_DROP_TRAMPOLINE_KIND => {152assert_eq!(a & Self::MODULE_MASK, 0);153assert_eq!(b, 0);154Self::ResourceDropTrampoline155}156157k => panic!(158"bad raw parts given to `FuncKey::from_raw_parts` call: ({a}, {b}), kind would be {k}"159),160}161}162163/// Unwrap a `FuncKey::DefinedWasmFunction` or else panic.164pub fn unwrap_defined_wasm_function(self) -> (StaticModuleIndex, DefinedFuncIndex) {165match self {166Self::DefinedWasmFunction(module, def_func) => (module, def_func),167_ => panic!("`FuncKey::unwrap_defined_wasm_function` called on {self:?}"),168}169}170171/// Unwrap a `FuncKey::ArrayToWasmTrampoline` or else panic.172pub fn unwrap_array_to_wasm_trampoline(self) -> (StaticModuleIndex, DefinedFuncIndex) {173match self {174Self::ArrayToWasmTrampoline(module, def_func) => (module, def_func),175_ => panic!("`FuncKey::unwrap_array_to_wasm_trampoline` called on {self:?}"),176}177}178179/// Unwrap a `FuncKey::WasmToArrayTrampoline` or else panic.180pub fn unwrap_wasm_to_array_trampoline(self) -> ModuleInternedTypeIndex {181match self {182Self::WasmToArrayTrampoline(ty) => ty,183_ => panic!("`FuncKey::unwrap_wasm_to_array_trampoline` called on {self:?}"),184}185}186187/// Unwrap a `FuncKey::WasmToBuiltinTrampoline` or else panic.188pub fn unwrap_wasm_to_builtin_trampoline(self) -> BuiltinFunctionIndex {189match self {190Self::WasmToBuiltinTrampoline(builtin) => builtin,191_ => panic!("`FuncKey::unwrap_wasm_to_builtin_trampoline` called on {self:?}"),192}193}194195/// Unwrap a `FuncKey::PulleyHostCall` or else panic.196pub fn unwrap_pulley_host_call(self) -> HostCall {197match self {198Self::PulleyHostCall(host_call) => host_call,199_ => panic!("`FuncKey::unwrap_pulley_host_call` called on {self:?}"),200}201}202203/// Unwrap a `FuncKey::ComponentTrampoline` or else panic.204#[cfg(feature = "component-model")]205pub fn unwrap_component_trampoline(self) -> component::TrampolineIndex {206match self {207Self::ComponentTrampoline(trampoline) => trampoline,208_ => panic!("`FuncKey::unwrap_component_trampoline` called on {self:?}"),209}210}211212/// Unwrap a `FuncKey::ResourceDropTrampoline` or else panic.213#[cfg(feature = "component-model")]214pub fn unwrap_resource_drop_trampoline(self) {215match self {216Self::ResourceDropTrampoline => {}217_ => panic!("`FuncKey::unwrap_resource_drop_trampoline` called on {self:?}"),218}219}220}221222223