wasmer_runtime_core_near/
backend.rs1use crate::{
2 error::{CompileResult, RuntimeError},
3 module::ModuleInner,
4 state::ModuleStateMap,
5 typed_func::Wasm,
6 types::{LocalFuncIndex, SigIndex},
7 vm,
8};
9
10use crate::{
11 cache::{Artifact, Error as CacheError},
12 codegen::BreakpointMap,
13 module::ModuleInfo,
14 sys::Memory,
15};
16use std::fmt;
17use std::{any::Any, ptr::NonNull};
18
19use std::collections::HashMap;
20
21use borsh::{BorshDeserialize, BorshSerialize};
22
23pub mod sys {
24 pub use crate::sys::*;
25}
26pub use crate::sig_registry::SigRegistry;
27
28#[derive(Copy, Clone, Debug)]
30pub enum Architecture {
31 X64,
33
34 Aarch64,
36}
37
38#[repr(u8)]
40#[derive(Copy, Clone, Debug)]
41pub enum InlineBreakpointType {
42 Middleware,
44}
45
46#[derive(Clone, Debug)]
48pub struct InlineBreakpoint {
49 pub size: usize,
51
52 pub ty: InlineBreakpointType,
54}
55
56pub struct Token {
59 _private: (),
60}
61
62impl Token {
63 pub(crate) fn generate() -> Self {
64 Self { _private: () }
65 }
66}
67
68#[derive(Copy, Clone, Debug)]
69pub enum MemoryBoundCheckMode {
70 Default,
71 Enable,
72 Disable,
73}
74
75impl Default for MemoryBoundCheckMode {
76 fn default() -> MemoryBoundCheckMode {
77 MemoryBoundCheckMode::Default
78 }
79}
80
81#[derive(Debug, Default)]
86pub struct Features {
87 pub simd: bool,
91 pub threads: bool,
95}
96
97#[derive(Debug)]
101pub struct BackendCompilerConfig(pub Box<dyn Any + 'static>);
102
103impl BackendCompilerConfig {
104 pub fn get_specific<T: 'static>(&self) -> Option<&T> {
106 self.0.downcast_ref::<T>()
107 }
108}
109
110#[derive(Debug)]
112pub struct CompilerConfig {
113 pub symbol_map: Option<HashMap<u32, String>>,
115
116 pub memory_bound_check_mode: MemoryBoundCheckMode,
118
119 pub enforce_stack_check: bool,
125
126 pub track_state: bool,
128
129 pub full_preemption: bool,
136
137 pub nan_canonicalization: bool,
140
141 pub enable_verification: bool,
147
148 pub features: Features,
149
150 pub triple: Option<String>,
152 pub cpu_name: Option<String>,
153 pub cpu_features: Option<String>,
154
155 pub backend_specific_config: Option<BackendCompilerConfig>,
156
157 pub generate_debug_info: bool,
158}
159
160impl Default for CompilerConfig {
161 fn default() -> Self {
162 Self {
163 symbol_map: Default::default(),
164 memory_bound_check_mode: Default::default(),
165 enforce_stack_check: Default::default(),
166 track_state: Default::default(),
167 full_preemption: Default::default(),
168 nan_canonicalization: Default::default(),
169 features: Default::default(),
170 triple: Default::default(),
171 cpu_name: Default::default(),
172 cpu_features: Default::default(),
173 backend_specific_config: Default::default(),
174 generate_debug_info: Default::default(),
175
176 enable_verification: cfg!(test) || cfg!(debug_assertions),
180 }
181 }
182}
183
184impl CompilerConfig {
185 pub(crate) fn should_generate_debug_info(&self) -> bool {
189 cfg!(feature = "generate-debug-information") && self.generate_debug_info
190 }
191}
192
193#[derive(Clone, Debug, Default, Serialize, Deserialize, BorshSerialize, BorshDeserialize)]
195pub struct ExceptionTable {
196 pub offset_to_code: HashMap<usize, ExceptionCode>,
198}
199
200impl ExceptionTable {
201 pub fn new() -> Self {
202 Self::default()
203 }
204}
205
206#[derive(
208 Copy,
209 Clone,
210 Debug,
211 Eq,
212 PartialEq,
213 Ord,
214 PartialOrd,
215 Serialize,
216 Deserialize,
217 BorshSerialize,
218 BorshDeserialize,
219)]
220#[borsh(use_discriminant=true)]
221pub enum ExceptionCode {
222 Unreachable = 0,
224 IncorrectCallIndirectSignature = 1,
226 MemoryOutOfBounds = 2,
228 CallIndirectOOB = 3,
230 IllegalArithmetic = 4,
232 MisalignedAtomicAccess = 5,
234}
235
236impl fmt::Display for ExceptionCode {
237 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
238 write!(
239 f,
240 "{}",
241 match self {
242 ExceptionCode::Unreachable => "unreachable",
243 ExceptionCode::IncorrectCallIndirectSignature => {
244 "incorrect `call_indirect` signature"
245 }
246 ExceptionCode::MemoryOutOfBounds => "memory out-of-bounds access",
247 ExceptionCode::CallIndirectOOB => "`call_indirect` out-of-bounds",
248 ExceptionCode::IllegalArithmetic => "illegal arithmetic operation",
249 ExceptionCode::MisalignedAtomicAccess => "misaligned atomic access",
250 }
251 )
252 }
253}
254
255pub trait Compiler {
256 fn compile(
260 &self,
261 wasm: &[u8],
262 comp_conf: CompilerConfig,
263 _: Token,
264 ) -> CompileResult<ModuleInner>;
265
266 unsafe fn from_cache(&self, cache: Artifact, _: Token) -> Result<ModuleInner, CacheError>;
267}
268
269pub trait RunnableModule: Send + Sync {
270 fn get_func(
273 &self,
274 info: &ModuleInfo,
275 local_func_index: LocalFuncIndex,
276 ) -> Option<NonNull<vm::Func>>;
277
278 fn get_module_state_map(&self) -> Option<ModuleStateMap> {
279 None
280 }
281
282 fn get_breakpoints(&self) -> Option<BreakpointMap> {
283 None
284 }
285
286 fn get_exception_table(&self) -> Option<&ExceptionTable> {
287 None
288 }
289
290 unsafe fn patch_local_function(&self, _idx: usize, _target_address: usize) -> bool {
291 false
292 }
293
294 fn get_trampoline(&self, info: &ModuleInfo, sig_index: SigIndex) -> Option<Wasm>;
298
299 unsafe fn do_early_trap(&self, data: RuntimeError) -> !;
301
302 fn get_code(&self) -> Option<&[u8]> {
304 None
305 }
306
307 fn get_offsets(&self) -> Option<Vec<usize>> {
309 None
310 }
311
312 fn get_local_function_offsets(&self) -> Option<Vec<usize>> {
314 None
315 }
316
317 fn get_inline_breakpoint_size(&self, _arch: Architecture) -> Option<usize> {
319 None
320 }
321
322 fn read_inline_breakpoint(
327 &self,
328 _arch: Architecture,
329 _code: &[u8],
330 ) -> Option<InlineBreakpoint> {
331 None
332 }
333}
334
335pub trait CacheGen: Send + Sync {
336 fn generate_cache(&self) -> Result<(Box<[u8]>, Memory), CacheError>;
337}