wasmtime_cranelift_shared/
lib.rs1use cranelift_codegen::{
2 binemit,
3 ir::{self, ExternalName, UserExternalNameRef},
4 settings, FinalizedMachReloc, FinalizedRelocTarget, MachTrap,
5};
6use wasmtime_environ::{FlagValue, FuncIndex, Trap, TrapInformation};
7
8pub mod isa_builder;
9mod obj;
10pub use obj::*;
11mod compiled_function;
12pub use compiled_function::*;
13
14#[derive(Debug, Clone, PartialEq, Eq)]
16pub struct Relocation {
17 pub reloc: binemit::Reloc,
19 pub reloc_target: RelocationTarget,
21 pub offset: binemit::CodeOffset,
23 pub addend: binemit::Addend,
25}
26
27#[derive(Debug, Copy, Clone, PartialEq, Eq)]
29pub enum RelocationTarget {
30 UserFunc(FuncIndex),
32 LibCall(ir::LibCall),
34}
35
36pub fn clif_flags_to_wasmtime(
38 flags: impl IntoIterator<Item = settings::Value>,
39) -> Vec<(&'static str, FlagValue<'static>)> {
40 flags
41 .into_iter()
42 .map(|val| (val.name, to_flag_value(&val)))
43 .collect()
44}
45
46fn to_flag_value(v: &settings::Value) -> FlagValue<'static> {
47 match v.kind() {
48 settings::SettingKind::Enum => FlagValue::Enum(v.as_enum().unwrap()),
49 settings::SettingKind::Num => FlagValue::Num(v.as_num().unwrap()),
50 settings::SettingKind::Bool => FlagValue::Bool(v.as_bool().unwrap()),
51 settings::SettingKind::Preset => unreachable!(),
52 }
53}
54
55const DEBUG_ASSERT_TRAP_CODE: u16 = u16::MAX;
57
58pub const ALWAYS_TRAP_CODE: u16 = 100;
63
64pub const CANNOT_ENTER_CODE: u16 = 101;
68
69pub fn mach_trap_to_trap(trap: &MachTrap) -> Option<TrapInformation> {
71 let &MachTrap { offset, code } = trap;
72 Some(TrapInformation {
73 code_offset: offset,
74 trap_code: match code {
75 ir::TrapCode::StackOverflow => Trap::StackOverflow,
76 ir::TrapCode::HeapOutOfBounds => Trap::MemoryOutOfBounds,
77 ir::TrapCode::HeapMisaligned => Trap::HeapMisaligned,
78 ir::TrapCode::TableOutOfBounds => Trap::TableOutOfBounds,
79 ir::TrapCode::IndirectCallToNull => Trap::IndirectCallToNull,
80 ir::TrapCode::BadSignature => Trap::BadSignature,
81 ir::TrapCode::IntegerOverflow => Trap::IntegerOverflow,
82 ir::TrapCode::IntegerDivisionByZero => Trap::IntegerDivisionByZero,
83 ir::TrapCode::BadConversionToInteger => Trap::BadConversionToInteger,
84 ir::TrapCode::UnreachableCodeReached => Trap::UnreachableCodeReached,
85 ir::TrapCode::Interrupt => Trap::Interrupt,
86 ir::TrapCode::User(ALWAYS_TRAP_CODE) => Trap::AlwaysTrapAdapter,
87 ir::TrapCode::User(CANNOT_ENTER_CODE) => Trap::CannotEnterComponent,
88 ir::TrapCode::NullReference => Trap::NullReference,
89
90 ir::TrapCode::User(DEBUG_ASSERT_TRAP_CODE) => return None,
94
95 ir::TrapCode::User(_) => unreachable!(),
97 },
98 })
99}
100
101fn mach_reloc_to_reloc<F>(reloc: &FinalizedMachReloc, transform_user_func_ref: F) -> Relocation
104where
105 F: Fn(UserExternalNameRef) -> (u32, u32),
106{
107 let &FinalizedMachReloc {
108 offset,
109 kind,
110 ref target,
111 addend,
112 } = reloc;
113 let reloc_target = match *target {
114 FinalizedRelocTarget::ExternalName(ExternalName::User(user_func_ref)) => {
115 let (namespace, index) = transform_user_func_ref(user_func_ref);
116 debug_assert_eq!(namespace, 0);
117 RelocationTarget::UserFunc(FuncIndex::from_u32(index))
118 }
119 FinalizedRelocTarget::ExternalName(ExternalName::LibCall(libcall)) => {
120 RelocationTarget::LibCall(libcall)
121 }
122 _ => panic!("unrecognized external name"),
123 };
124 Relocation {
125 reloc: kind,
126 reloc_target,
127 offset,
128 addend,
129 }
130}