/src/wasmtime/crates/environ/src/compile/mod.rs
Line | Count | Source |
1 | | //! A `Compilation` contains the compiled function bodies for a WebAssembly |
2 | | //! module. |
3 | | |
4 | | use crate::error::Result; |
5 | | use crate::prelude::*; |
6 | | use crate::{ |
7 | | DefinedFuncIndex, FlagValue, FuncKey, FunctionLoc, ObjectKind, PrimaryMap, StaticModuleIndex, |
8 | | TripleExt, Tunables, WasmError, obj, |
9 | | }; |
10 | | use object::write::{Object, SymbolId}; |
11 | | use object::{Architecture, BinaryFormat, FileFlags}; |
12 | | use std::any::Any; |
13 | | use std::borrow::Cow; |
14 | | use std::fmt; |
15 | | use std::path; |
16 | | use std::sync::Arc; |
17 | | |
18 | | mod address_map; |
19 | | mod frame_table; |
20 | | mod module_artifacts; |
21 | | mod module_environ; |
22 | | mod module_types; |
23 | | mod stack_maps; |
24 | | mod trap_encoding; |
25 | | |
26 | | pub use self::address_map::*; |
27 | | pub use self::frame_table::*; |
28 | | pub use self::module_artifacts::*; |
29 | | pub use self::module_environ::*; |
30 | | pub use self::module_types::*; |
31 | | pub use self::stack_maps::*; |
32 | | pub use self::trap_encoding::*; |
33 | | |
34 | | /// An error while compiling WebAssembly to machine code. |
35 | | #[derive(Debug)] |
36 | | pub enum CompileError { |
37 | | /// A wasm translation error occurred. |
38 | | Wasm(WasmError), |
39 | | |
40 | | /// A compilation error occurred. |
41 | | Codegen(String), |
42 | | |
43 | | /// A compilation error occurred. |
44 | | DebugInfoNotSupported, |
45 | | } |
46 | | |
47 | | impl fmt::Display for CompileError { |
48 | 99 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
49 | 99 | match self { |
50 | 98 | CompileError::Wasm(_) => write!(f, "WebAssembly translation error"), |
51 | 1 | CompileError::Codegen(s) => write!(f, "Compilation error: {s}"), |
52 | | CompileError::DebugInfoNotSupported => { |
53 | 0 | write!(f, "Debug info is not supported with this configuration") |
54 | | } |
55 | | } |
56 | 99 | } |
57 | | } |
58 | | |
59 | | impl From<WasmError> for CompileError { |
60 | 69.2k | fn from(err: WasmError) -> CompileError { |
61 | 69.2k | CompileError::Wasm(err) |
62 | 69.2k | } |
63 | | } |
64 | | |
65 | | impl core::error::Error for CompileError { |
66 | 198 | fn source(&self) -> Option<&(dyn core::error::Error + 'static)> { |
67 | 198 | match self { |
68 | 196 | CompileError::Wasm(e) => Some(e), |
69 | 2 | _ => None, |
70 | | } |
71 | 198 | } |
72 | | } |
73 | | |
74 | | /// Implementation of an incremental compilation's key/value cache store. |
75 | | /// |
76 | | /// In theory, this could just be Cranelift's `CacheKvStore` trait, but it is not as we want to |
77 | | /// make sure that wasmtime isn't too tied to Cranelift internals (and as a matter of fact, we |
78 | | /// can't depend on the Cranelift trait here). |
79 | | pub trait CacheStore: Send + Sync + std::fmt::Debug { |
80 | | /// Try to retrieve an arbitrary cache key entry, and returns a reference to bytes that were |
81 | | /// inserted via `Self::insert` before. |
82 | | fn get(&self, key: &[u8]) -> Option<Cow<'_, [u8]>>; |
83 | | |
84 | | /// Given an arbitrary key and bytes, stores them in the cache. |
85 | | /// |
86 | | /// Returns false when insertion in the cache failed. |
87 | | fn insert(&self, key: &[u8], value: Vec<u8>) -> bool; |
88 | | } |
89 | | |
90 | | /// Abstract trait representing the ability to create a `Compiler` below. |
91 | | /// |
92 | | /// This is used in Wasmtime to separate compiler implementations, currently |
93 | | /// mostly used to separate Cranelift from Wasmtime itself. |
94 | | pub trait CompilerBuilder: Send + Sync + fmt::Debug { |
95 | | /// Sets the target of compilation to the target specified. |
96 | | fn target(&mut self, target: target_lexicon::Triple) -> Result<()>; |
97 | | |
98 | | /// Enables clif output in the directory specified. |
99 | 0 | fn clif_dir(&mut self, _path: &path::Path) -> Result<()> { |
100 | 0 | bail!("clif output not supported"); |
101 | 0 | } Unexecuted instantiation: <wasmtime_internal_winch::builder::Builder as wasmtime_environ::compile::CompilerBuilder>::clif_dir Unexecuted instantiation: <_ as wasmtime_environ::compile::CompilerBuilder>::clif_dir |
102 | | |
103 | | /// Returns the currently configured target triple that compilation will |
104 | | /// produce artifacts for. |
105 | | fn triple(&self) -> &target_lexicon::Triple; |
106 | | |
107 | | /// Compiler-specific method to configure various settings in the compiler |
108 | | /// itself. |
109 | | /// |
110 | | /// This is expected to be defined per-compiler. Compilers should return |
111 | | /// errors for unknown names/values. |
112 | | fn set(&mut self, name: &str, val: &str) -> Result<()>; |
113 | | |
114 | | /// Compiler-specific method for configuring settings. |
115 | | /// |
116 | | /// Same as [`CompilerBuilder::set`] except for enabling boolean flags. |
117 | | /// Currently cranelift uses this to sometimes enable a family of settings. |
118 | | fn enable(&mut self, name: &str) -> Result<()>; |
119 | | |
120 | | /// Returns a list of all possible settings that can be configured with |
121 | | /// [`CompilerBuilder::set`] and [`CompilerBuilder::enable`]. |
122 | | fn settings(&self) -> Vec<Setting>; |
123 | | |
124 | | /// Enables Cranelift's incremental compilation cache, using the given `CacheStore` |
125 | | /// implementation. |
126 | | /// |
127 | | /// This will return an error if the compiler does not support incremental compilation. |
128 | | fn enable_incremental_compilation(&mut self, cache_store: Arc<dyn CacheStore>) -> Result<()>; |
129 | | |
130 | | /// Set the tunables for this compiler. |
131 | | fn set_tunables(&mut self, tunables: Tunables) -> Result<()>; |
132 | | |
133 | | /// Get the tunables used by this compiler. |
134 | | fn tunables(&self) -> Option<&Tunables>; |
135 | | |
136 | | /// Builds a new [`Compiler`] object from this configuration. |
137 | | fn build(&self) -> Result<Box<dyn Compiler>>; |
138 | | |
139 | | /// Enables or disables wmemcheck during runtime according to the wmemcheck CLI flag. |
140 | 4.44k | fn wmemcheck(&mut self, _enable: bool) {}<wasmtime_internal_winch::builder::Builder as wasmtime_environ::compile::CompilerBuilder>::wmemcheck Line | Count | Source | 140 | 4.44k | fn wmemcheck(&mut self, _enable: bool) {} |
Unexecuted instantiation: <_ as wasmtime_environ::compile::CompilerBuilder>::wmemcheck |
141 | | } |
142 | | |
143 | | /// Description of compiler settings returned by [`CompilerBuilder::settings`]. |
144 | | #[derive(Clone, Copy, Debug)] |
145 | | pub struct Setting { |
146 | | /// The name of the setting. |
147 | | pub name: &'static str, |
148 | | /// The description of the setting. |
149 | | pub description: &'static str, |
150 | | /// The kind of the setting. |
151 | | pub kind: SettingKind, |
152 | | /// The supported values of the setting (for enum values). |
153 | | pub values: Option<&'static [&'static str]>, |
154 | | } |
155 | | |
156 | | /// Different kinds of [`Setting`] values that can be configured in a |
157 | | /// [`CompilerBuilder`] |
158 | | #[derive(Clone, Copy, Debug)] |
159 | | pub enum SettingKind { |
160 | | /// The setting is an enumeration, meaning it's one of a set of values. |
161 | | Enum, |
162 | | /// The setting is a number. |
163 | | Num, |
164 | | /// The setting is a boolean. |
165 | | Bool, |
166 | | /// The setting is a preset. |
167 | | Preset, |
168 | | } |
169 | | |
170 | | /// The result of compiling a single function body. |
171 | | pub struct CompiledFunctionBody { |
172 | | /// The code. This is whatever type the `Compiler` implementation wants it |
173 | | /// to be, we just shepherd it around. |
174 | | pub code: Box<dyn Any + Send + Sync>, |
175 | | /// Whether the compiled function needs a GC heap to run; that is, whether |
176 | | /// it reads a struct field, allocates, an array, or etc... |
177 | | pub needs_gc_heap: bool, |
178 | | } |
179 | | |
180 | | /// An implementation of a compiler which can compile WebAssembly functions to |
181 | | /// machine code and perform other miscellaneous tasks needed by the JIT runtime. |
182 | | /// |
183 | | /// The diagram below depicts typical usage of this trait: |
184 | | /// |
185 | | /// ```text |
186 | | /// +------+ |
187 | | /// | Wasm | |
188 | | /// +------+ |
189 | | /// | |
190 | | /// | |
191 | | /// Compiler::compile_function() |
192 | | /// | |
193 | | /// | |
194 | | /// V |
195 | | /// +----------------------+ |
196 | | /// | CompiledFunctionBody | |
197 | | /// +----------------------+ |
198 | | /// | | |
199 | | /// | | |
200 | | /// | When |
201 | | /// | Compiler::inlining_compiler() |
202 | | /// | is some |
203 | | /// | | |
204 | | /// When | |
205 | | /// Compiler::inlining_compiler() |-----------------. |
206 | | /// is none | | |
207 | | /// | | | |
208 | | /// | Optionally call | |
209 | | /// | InliningCompiler::inline() | |
210 | | /// | | | |
211 | | /// | | | |
212 | | /// | |-----------------' |
213 | | /// | | |
214 | | /// | | |
215 | | /// | V |
216 | | /// | InliningCompiler::finish_compiling() |
217 | | /// | | |
218 | | /// | | |
219 | | /// |------------------' |
220 | | /// | |
221 | | /// | |
222 | | /// Compiler::append_code() |
223 | | /// | |
224 | | /// | |
225 | | /// V |
226 | | /// +--------+ |
227 | | /// | Object | |
228 | | /// +--------+ |
229 | | /// ``` |
230 | | pub trait Compiler: Send + Sync { |
231 | | /// Get this compiler's inliner. |
232 | | /// |
233 | | /// Consumers of this trait **must** check for when when this method returns |
234 | | /// `Some(_)`, and **must** call `InliningCompiler::finish_compiling` on all |
235 | | /// `CompiledFunctionBody`s produced by this compiler in that case before |
236 | | /// passing the the compiled functions to `Compiler::append_code`, even if |
237 | | /// the consumer does not actually intend to do any inlining. This allows |
238 | | /// implementations of the trait to only translate to an internal |
239 | | /// representation in `Compiler::compile_*` methods so that they can then |
240 | | /// perform inlining afterwards if the consumer desires, and then finally |
241 | | /// proceed with compilng that internal representation to native code in |
242 | | /// `InliningCompiler::finish_compiling`. |
243 | | fn inlining_compiler(&self) -> Option<&dyn InliningCompiler>; |
244 | | |
245 | | /// Compiles the function `index` within `translation`. |
246 | | /// |
247 | | /// The body of the function is available in `data` and configuration |
248 | | /// values are also passed in via `tunables`. Type information in |
249 | | /// `translation` is all relative to `types`. |
250 | | fn compile_function( |
251 | | &self, |
252 | | translation: &ModuleTranslation<'_>, |
253 | | key: FuncKey, |
254 | | data: FunctionBodyData<'_>, |
255 | | types: &ModuleTypesBuilder, |
256 | | symbol: &str, |
257 | | ) -> Result<CompiledFunctionBody, CompileError>; |
258 | | |
259 | | /// Compile a trampoline for an array-call host function caller calling the |
260 | | /// `index`th Wasm function. |
261 | | /// |
262 | | /// The trampoline should save the necessary state to record the |
263 | | /// host-to-Wasm transition (e.g. registers used for fast stack walking). |
264 | | fn compile_trampoline( |
265 | | &self, |
266 | | translation: Option<&ModuleTranslation<'_>>, |
267 | | key: FuncKey, |
268 | | types: &ModuleTypesBuilder, |
269 | | symbol: &str, |
270 | | ) -> Result<CompiledFunctionBody, CompileError>; |
271 | | |
272 | | /// Returns the list of relocations required for a function from one of the |
273 | | /// previous `compile_*` functions above. |
274 | | fn compiled_function_relocation_targets<'a>( |
275 | | &'a self, |
276 | | func: &'a dyn Any, |
277 | | ) -> Box<dyn Iterator<Item = FuncKey> + 'a>; |
278 | | |
279 | | /// Appends a list of compiled functions to an in-memory object. |
280 | | /// |
281 | | /// This function will receive the same `Box<dyn Any>` produced as part of |
282 | | /// compilation from functions like `compile_function`, |
283 | | /// `compile_host_to_wasm_trampoline`, and other component-related shims. |
284 | | /// Internally this will take all of these functions and add information to |
285 | | /// the object such as: |
286 | | /// |
287 | | /// * Compiled code in a `.text` section |
288 | | /// * Unwind information in Wasmtime-specific sections |
289 | | /// * Relocations, if necessary, for the text section |
290 | | /// |
291 | | /// Each function is accompanied with its desired symbol name and the return |
292 | | /// value of this function is the symbol for each function as well as where |
293 | | /// each function was placed within the object. |
294 | | /// |
295 | | /// The `resolve_reloc` argument is intended to resolving relocations |
296 | | /// between function, chiefly resolving intra-module calls within one core |
297 | | /// wasm module. The closure here takes two arguments: |
298 | | /// |
299 | | /// 1. First, the index within `funcs` that is being resolved, |
300 | | /// |
301 | | /// 2. and next the `RelocationTarget` which is the relocation target to |
302 | | /// resolve. |
303 | | /// |
304 | | /// The return value is an index within `funcs` that the relocation points |
305 | | /// to. |
306 | | fn append_code( |
307 | | &self, |
308 | | obj: &mut Object<'static>, |
309 | | funcs: &[(String, FuncKey, Box<dyn Any + Send + Sync>)], |
310 | | resolve_reloc: &dyn Fn(usize, FuncKey) -> usize, |
311 | | ) -> Result<Vec<(Option<SymbolId>, FunctionLoc)>>; |
312 | | |
313 | | /// Creates a new `Object` file which is used to build the results of a |
314 | | /// compilation into. |
315 | | /// |
316 | | /// The returned object file will have an appropriate |
317 | | /// architecture/endianness for `self.triple()`, but at this time it is |
318 | | /// always an ELF file, regardless of target platform. |
319 | 127k | fn object(&self, kind: ObjectKind) -> Result<Object<'static>> { |
320 | | use target_lexicon::Architecture::*; |
321 | | |
322 | 127k | let triple = self.triple(); |
323 | 127k | let (arch, flags) = match triple.architecture { |
324 | 0 | X86_32(_) => (Architecture::I386, object::elf::FileFlags(0)), |
325 | 108k | X86_64 => (Architecture::X86_64, object::elf::FileFlags(0)), |
326 | 0 | Arm(_) => (Architecture::Arm, object::elf::FileFlags(0)), |
327 | 0 | Aarch64(_) => (Architecture::Aarch64, object::elf::FileFlags(0)), |
328 | 0 | S390x => (Architecture::S390x, object::elf::FileFlags(0)), |
329 | 0 | Riscv64(_) => (Architecture::Riscv64, object::elf::FileFlags(0)), |
330 | | // XXX: the `object` crate won't successfully build an object |
331 | | // with relocations and such if it doesn't know the |
332 | | // architecture, so just pretend we are riscv64. Yolo! |
333 | | // |
334 | | // Also note that we add some flags to `e_flags` in the object file |
335 | | // to indicate that it's pulley, not actually riscv64. This is used |
336 | | // by `wasmtime objdump` for example. |
337 | 0 | Pulley32 | Pulley32be => (Architecture::Riscv64, obj::EF_WASMTIME_PULLEY32), |
338 | 18.3k | Pulley64 | Pulley64be => (Architecture::Riscv64, obj::EF_WASMTIME_PULLEY64), |
339 | 0 | architecture => { |
340 | 0 | bail!("target architecture {architecture:?} is unsupported"); |
341 | | } |
342 | | }; |
343 | 127k | let mut obj = Object::new( |
344 | 127k | BinaryFormat::Elf, |
345 | 127k | arch, |
346 | 127k | match triple.endianness().unwrap() { |
347 | 127k | target_lexicon::Endianness::Little => object::Endianness::Little, |
348 | 0 | target_lexicon::Endianness::Big => object::Endianness::Big, |
349 | | }, |
350 | | ); |
351 | | obj.flags = FileFlags::Elf { |
352 | | os_abi: obj::ELFOSABI_WASMTIME, |
353 | 127k | e_flags: flags |
354 | 127k | | match kind { |
355 | 122k | ObjectKind::Module => obj::EF_WASMTIME_MODULE, |
356 | 4.72k | ObjectKind::Component => obj::EF_WASMTIME_COMPONENT, |
357 | | }, |
358 | | abi_version: 0, |
359 | | }; |
360 | 127k | Ok(obj) |
361 | 127k | } <wasmtime_internal_winch::compiler::Compiler as wasmtime_environ::compile::Compiler>::object Line | Count | Source | 319 | 6.02k | fn object(&self, kind: ObjectKind) -> Result<Object<'static>> { | 320 | | use target_lexicon::Architecture::*; | 321 | | | 322 | 6.02k | let triple = self.triple(); | 323 | 6.02k | let (arch, flags) = match triple.architecture { | 324 | 0 | X86_32(_) => (Architecture::I386, object::elf::FileFlags(0)), | 325 | 6.02k | X86_64 => (Architecture::X86_64, object::elf::FileFlags(0)), | 326 | 0 | Arm(_) => (Architecture::Arm, object::elf::FileFlags(0)), | 327 | 0 | Aarch64(_) => (Architecture::Aarch64, object::elf::FileFlags(0)), | 328 | 0 | S390x => (Architecture::S390x, object::elf::FileFlags(0)), | 329 | 0 | Riscv64(_) => (Architecture::Riscv64, object::elf::FileFlags(0)), | 330 | | // XXX: the `object` crate won't successfully build an object | 331 | | // with relocations and such if it doesn't know the | 332 | | // architecture, so just pretend we are riscv64. Yolo! | 333 | | // | 334 | | // Also note that we add some flags to `e_flags` in the object file | 335 | | // to indicate that it's pulley, not actually riscv64. This is used | 336 | | // by `wasmtime objdump` for example. | 337 | 0 | Pulley32 | Pulley32be => (Architecture::Riscv64, obj::EF_WASMTIME_PULLEY32), | 338 | 0 | Pulley64 | Pulley64be => (Architecture::Riscv64, obj::EF_WASMTIME_PULLEY64), | 339 | 0 | architecture => { | 340 | 0 | bail!("target architecture {architecture:?} is unsupported"); | 341 | | } | 342 | | }; | 343 | 6.02k | let mut obj = Object::new( | 344 | 6.02k | BinaryFormat::Elf, | 345 | 6.02k | arch, | 346 | 6.02k | match triple.endianness().unwrap() { | 347 | 6.02k | target_lexicon::Endianness::Little => object::Endianness::Little, | 348 | 0 | target_lexicon::Endianness::Big => object::Endianness::Big, | 349 | | }, | 350 | | ); | 351 | | obj.flags = FileFlags::Elf { | 352 | | os_abi: obj::ELFOSABI_WASMTIME, | 353 | 6.02k | e_flags: flags | 354 | 6.02k | | match kind { | 355 | 5.89k | ObjectKind::Module => obj::EF_WASMTIME_MODULE, | 356 | 131 | ObjectKind::Component => obj::EF_WASMTIME_COMPONENT, | 357 | | }, | 358 | | abi_version: 0, | 359 | | }; | 360 | 6.02k | Ok(obj) | 361 | 6.02k | } |
<wasmtime_internal_cranelift::compiler::Compiler as wasmtime_environ::compile::Compiler>::object Line | Count | Source | 319 | 121k | fn object(&self, kind: ObjectKind) -> Result<Object<'static>> { | 320 | | use target_lexicon::Architecture::*; | 321 | | | 322 | 121k | let triple = self.triple(); | 323 | 121k | let (arch, flags) = match triple.architecture { | 324 | 0 | X86_32(_) => (Architecture::I386, object::elf::FileFlags(0)), | 325 | 102k | X86_64 => (Architecture::X86_64, object::elf::FileFlags(0)), | 326 | 0 | Arm(_) => (Architecture::Arm, object::elf::FileFlags(0)), | 327 | 0 | Aarch64(_) => (Architecture::Aarch64, object::elf::FileFlags(0)), | 328 | 0 | S390x => (Architecture::S390x, object::elf::FileFlags(0)), | 329 | 0 | Riscv64(_) => (Architecture::Riscv64, object::elf::FileFlags(0)), | 330 | | // XXX: the `object` crate won't successfully build an object | 331 | | // with relocations and such if it doesn't know the | 332 | | // architecture, so just pretend we are riscv64. Yolo! | 333 | | // | 334 | | // Also note that we add some flags to `e_flags` in the object file | 335 | | // to indicate that it's pulley, not actually riscv64. This is used | 336 | | // by `wasmtime objdump` for example. | 337 | 0 | Pulley32 | Pulley32be => (Architecture::Riscv64, obj::EF_WASMTIME_PULLEY32), | 338 | 18.3k | Pulley64 | Pulley64be => (Architecture::Riscv64, obj::EF_WASMTIME_PULLEY64), | 339 | 0 | architecture => { | 340 | 0 | bail!("target architecture {architecture:?} is unsupported"); | 341 | | } | 342 | | }; | 343 | 121k | let mut obj = Object::new( | 344 | 121k | BinaryFormat::Elf, | 345 | 121k | arch, | 346 | 121k | match triple.endianness().unwrap() { | 347 | 121k | target_lexicon::Endianness::Little => object::Endianness::Little, | 348 | 0 | target_lexicon::Endianness::Big => object::Endianness::Big, | 349 | | }, | 350 | | ); | 351 | | obj.flags = FileFlags::Elf { | 352 | | os_abi: obj::ELFOSABI_WASMTIME, | 353 | 121k | e_flags: flags | 354 | 121k | | match kind { | 355 | 116k | ObjectKind::Module => obj::EF_WASMTIME_MODULE, | 356 | 4.59k | ObjectKind::Component => obj::EF_WASMTIME_COMPONENT, | 357 | | }, | 358 | | abi_version: 0, | 359 | | }; | 360 | 121k | Ok(obj) | 361 | 121k | } |
Unexecuted instantiation: <_ as wasmtime_environ::compile::Compiler>::object |
362 | | |
363 | | /// Returns the target triple that this compiler is compiling for. |
364 | | fn triple(&self) -> &target_lexicon::Triple; |
365 | | |
366 | | /// Returns the alignment necessary to align values to the page size of the |
367 | | /// compilation target. Note that this may be an upper-bound where the |
368 | | /// alignment is larger than necessary for some platforms since it may |
369 | | /// depend on the platform's runtime configuration. |
370 | 382k | fn page_size_align(&self) -> u64 { |
371 | | // Conservatively assume the max-of-all-supported-hosts for pulley |
372 | | // and round up to 64k. |
373 | 382k | if self.triple().is_pulley() { |
374 | 22.5k | return 0x10000; |
375 | 360k | } |
376 | | |
377 | | use target_lexicon::*; |
378 | 360k | match (self.triple().operating_system, self.triple().architecture) { |
379 | | ( |
380 | | OperatingSystem::MacOSX { .. } |
381 | | | OperatingSystem::Darwin(_) |
382 | | | OperatingSystem::IOS(_) |
383 | | | OperatingSystem::TvOS(_), |
384 | | Architecture::Aarch64(..), |
385 | 0 | ) => 0x4000, |
386 | | // According to |
387 | | // https://devblogs.microsoft.com/oldnewthing/20210510-00/?p=105200 |
388 | | // it seems like windows always use a 4k page size. |
389 | 0 | (OperatingSystem::Windows, Architecture::Aarch64(..)) => 0x1000, |
390 | | // 64 KB is the maximal page size (i.e. memory translation granule size) |
391 | | // supported by the architecture and is used on some platforms. |
392 | 0 | (_, Architecture::Aarch64(..)) => 0x10000, |
393 | 360k | _ => 0x1000, |
394 | | } |
395 | 382k | } <wasmtime_internal_winch::compiler::Compiler as wasmtime_environ::compile::Compiler>::page_size_align Line | Count | Source | 370 | 6.87k | fn page_size_align(&self) -> u64 { | 371 | | // Conservatively assume the max-of-all-supported-hosts for pulley | 372 | | // and round up to 64k. | 373 | 6.87k | if self.triple().is_pulley() { | 374 | 0 | return 0x10000; | 375 | 6.87k | } | 376 | | | 377 | | use target_lexicon::*; | 378 | 6.87k | match (self.triple().operating_system, self.triple().architecture) { | 379 | | ( | 380 | | OperatingSystem::MacOSX { .. } | 381 | | | OperatingSystem::Darwin(_) | 382 | | | OperatingSystem::IOS(_) | 383 | | | OperatingSystem::TvOS(_), | 384 | | Architecture::Aarch64(..), | 385 | 0 | ) => 0x4000, | 386 | | // According to | 387 | | // https://devblogs.microsoft.com/oldnewthing/20210510-00/?p=105200 | 388 | | // it seems like windows always use a 4k page size. | 389 | 0 | (OperatingSystem::Windows, Architecture::Aarch64(..)) => 0x1000, | 390 | | // 64 KB is the maximal page size (i.e. memory translation granule size) | 391 | | // supported by the architecture and is used on some platforms. | 392 | 0 | (_, Architecture::Aarch64(..)) => 0x10000, | 393 | 6.87k | _ => 0x1000, | 394 | | } | 395 | 6.87k | } |
<wasmtime_internal_cranelift::compiler::Compiler as wasmtime_environ::compile::Compiler>::page_size_align Line | Count | Source | 370 | 375k | fn page_size_align(&self) -> u64 { | 371 | | // Conservatively assume the max-of-all-supported-hosts for pulley | 372 | | // and round up to 64k. | 373 | 375k | if self.triple().is_pulley() { | 374 | 22.5k | return 0x10000; | 375 | 353k | } | 376 | | | 377 | | use target_lexicon::*; | 378 | 353k | match (self.triple().operating_system, self.triple().architecture) { | 379 | | ( | 380 | | OperatingSystem::MacOSX { .. } | 381 | | | OperatingSystem::Darwin(_) | 382 | | | OperatingSystem::IOS(_) | 383 | | | OperatingSystem::TvOS(_), | 384 | | Architecture::Aarch64(..), | 385 | 0 | ) => 0x4000, | 386 | | // According to | 387 | | // https://devblogs.microsoft.com/oldnewthing/20210510-00/?p=105200 | 388 | | // it seems like windows always use a 4k page size. | 389 | 0 | (OperatingSystem::Windows, Architecture::Aarch64(..)) => 0x1000, | 390 | | // 64 KB is the maximal page size (i.e. memory translation granule size) | 391 | | // supported by the architecture and is used on some platforms. | 392 | 0 | (_, Architecture::Aarch64(..)) => 0x10000, | 393 | 353k | _ => 0x1000, | 394 | | } | 395 | 375k | } |
Unexecuted instantiation: <_ as wasmtime_environ::compile::Compiler>::page_size_align |
396 | | |
397 | | /// Returns a list of configured settings for this compiler. |
398 | | fn flags(&self) -> Vec<(&'static str, FlagValue<'static>)>; |
399 | | |
400 | | /// Same as [`Compiler::flags`], but ISA-specific (a cranelift-ism) |
401 | | fn isa_flags(&self) -> Vec<(&'static str, FlagValue<'static>)>; |
402 | | |
403 | | /// Get a flag indicating whether branch protection is enabled. |
404 | | fn is_branch_protection_enabled(&self) -> bool; |
405 | | |
406 | | /// Returns a suitable compiler usable for component-related compilations. |
407 | | /// |
408 | | /// Note that the `ComponentCompiler` trait can also be implemented for |
409 | | /// `Self` in which case this function would simply return `self`. |
410 | | #[cfg(feature = "component-model")] |
411 | | fn component_compiler(&self) -> &dyn crate::component::ComponentCompiler; |
412 | | |
413 | | /// Appends generated DWARF sections to the `obj` specified. |
414 | | /// |
415 | | /// The `translations` track all compiled functions and `get_func` can be |
416 | | /// used to acquire the metadata for a particular function within a module. |
417 | | fn append_dwarf<'a>( |
418 | | &self, |
419 | | obj: &mut Object<'_>, |
420 | | translations: &'a PrimaryMap<StaticModuleIndex, ModuleTranslation<'a>>, |
421 | | get_func: &'a dyn Fn( |
422 | | StaticModuleIndex, |
423 | | DefinedFuncIndex, |
424 | | ) -> (Option<SymbolId>, &'a (dyn Any + Send + Sync)), |
425 | | dwarf_package_bytes: Option<&'a [u8]>, |
426 | | tunables: &'a Tunables, |
427 | | ) -> Result<()>; |
428 | | |
429 | | /// Creates a new System V Common Information Entry for the ISA. |
430 | | /// |
431 | | /// Returns `None` if the ISA does not support System V unwind information. |
432 | 0 | fn create_systemv_cie(&self) -> Option<gimli::write::CommonInformationEntry> { |
433 | | // By default, an ISA cannot create a System V CIE. |
434 | 0 | None |
435 | 0 | } |
436 | | |
437 | | /// Invoked at the end of a module or component compilation and signals |
438 | | /// that any transient caches across functions can now be dropped. |
439 | | fn release_caches(&self); |
440 | | } |
441 | | |
442 | | /// An inlining compiler. |
443 | | pub trait InliningCompiler: Sync + Send { |
444 | | /// Enumerate the function calls that the given `func` makes. |
445 | | fn calls(&self, func: &CompiledFunctionBody, calls: &mut IndexSet<FuncKey>) -> Result<()>; |
446 | | |
447 | | /// Get the abstract size of the given function, for the purposes of |
448 | | /// inlining heuristics. |
449 | | fn size(&self, func: &CompiledFunctionBody) -> u32; |
450 | | |
451 | | /// Process this function for inlining. |
452 | | /// |
453 | | /// Implementations should call `get_callee` for each of their direct |
454 | | /// function call sites and if `get_callee` returns `Some(_)`, they should |
455 | | /// inline the given function body into that call site. |
456 | | fn inline<'a>( |
457 | | &self, |
458 | | func: &mut CompiledFunctionBody, |
459 | | get_callee: &'a mut dyn FnMut(FuncKey) -> Option<&'a CompiledFunctionBody>, |
460 | | ) -> Result<()>; |
461 | | |
462 | | /// Finish compiling the given function. |
463 | | /// |
464 | | /// This method **must** be called before passing the |
465 | | /// `CompiledFunctionBody`'s contents to `Compiler::append_code`, even if no |
466 | | /// inlining was performed. |
467 | | fn finish_compiling( |
468 | | &self, |
469 | | func: &mut CompiledFunctionBody, |
470 | | input: Option<wasmparser::FunctionBody<'_>>, |
471 | | symbol: &str, |
472 | | ) -> Result<()>; |
473 | | } |