Coverage Report

Created: 2026-09-14 07:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}