Coverage Report

Created: 2024-10-16 07:58

/src/wasmer/lib/compiler-cranelift/src/config.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::compiler::CraneliftCompiler;
2
use cranelift_codegen::isa::{lookup, TargetIsa};
3
use cranelift_codegen::settings::{self, Configurable};
4
use cranelift_codegen::CodegenResult;
5
use std::sync::Arc;
6
use wasmer_compiler::{Compiler, CompilerConfig, Engine, EngineBuilder, ModuleMiddleware};
7
use wasmer_types::{Architecture, CpuFeature, Target};
8
9
// Runtime Environment
10
11
/// Possible optimization levels for the Cranelift codegen backend.
12
#[non_exhaustive]
13
#[derive(Clone, Debug)]
14
pub enum CraneliftOptLevel {
15
    /// No optimizations performed, minimizes compilation time by disabling most
16
    /// optimizations.
17
    None,
18
    /// Generates the fastest possible code, but may take longer.
19
    Speed,
20
    /// Similar to `speed`, but also performs transformations aimed at reducing
21
    /// code size.
22
    SpeedAndSize,
23
}
24
25
/// Global configuration options used to create an
26
/// `wasmer_engine::Engine` and customize its behavior.
27
///
28
/// This structure exposes a builder-like interface and is primarily
29
/// consumed by `wasmer_engine::Engine::new`.
30
#[derive(Debug, Clone)]
31
pub struct Cranelift {
32
    enable_nan_canonicalization: bool,
33
    enable_verifier: bool,
34
    enable_pic: bool,
35
    opt_level: CraneliftOptLevel,
36
    /// The middleware chain.
37
    pub(crate) middlewares: Vec<Arc<dyn ModuleMiddleware>>,
38
}
39
40
impl Cranelift {
41
    /// Creates a new configuration object with the default configuration
42
    /// specified.
43
5.00k
    pub fn new() -> Self {
44
5.00k
        Self {
45
5.00k
            enable_nan_canonicalization: false,
46
5.00k
            enable_verifier: false,
47
5.00k
            opt_level: CraneliftOptLevel::Speed,
48
5.00k
            enable_pic: false,
49
5.00k
            middlewares: vec![],
50
5.00k
        }
51
5.00k
    }
Unexecuted instantiation: <wasmer_compiler_cranelift::config::Cranelift>::new
Unexecuted instantiation: <wasmer_compiler_cranelift::config::Cranelift>::new
Unexecuted instantiation: <wasmer_compiler_cranelift::config::Cranelift>::new
Unexecuted instantiation: <wasmer_compiler_cranelift::config::Cranelift>::new
<wasmer_compiler_cranelift::config::Cranelift>::new
Line
Count
Source
43
5.00k
    pub fn new() -> Self {
44
5.00k
        Self {
45
5.00k
            enable_nan_canonicalization: false,
46
5.00k
            enable_verifier: false,
47
5.00k
            opt_level: CraneliftOptLevel::Speed,
48
5.00k
            enable_pic: false,
49
5.00k
            middlewares: vec![],
50
5.00k
        }
51
5.00k
    }
Unexecuted instantiation: <wasmer_compiler_cranelift::config::Cranelift>::new
Unexecuted instantiation: <wasmer_compiler_cranelift::config::Cranelift>::new
52
53
    /// Enable NaN canonicalization.
54
    ///
55
    /// NaN canonicalization is useful when trying to run WebAssembly
56
    /// deterministically across different architectures.
57
5.00k
    pub fn canonicalize_nans(&mut self, enable: bool) -> &mut Self {
58
5.00k
        self.enable_nan_canonicalization = enable;
59
5.00k
        self
60
5.00k
    }
Unexecuted instantiation: <wasmer_compiler_cranelift::config::Cranelift>::canonicalize_nans
Unexecuted instantiation: <wasmer_compiler_cranelift::config::Cranelift>::canonicalize_nans
<wasmer_compiler_cranelift::config::Cranelift>::canonicalize_nans
Line
Count
Source
57
5.00k
    pub fn canonicalize_nans(&mut self, enable: bool) -> &mut Self {
58
5.00k
        self.enable_nan_canonicalization = enable;
59
5.00k
        self
60
5.00k
    }
Unexecuted instantiation: <wasmer_compiler_cranelift::config::Cranelift>::canonicalize_nans
Unexecuted instantiation: <wasmer_compiler_cranelift::config::Cranelift>::canonicalize_nans
61
62
    /// The optimization levels when optimizing the IR.
63
0
    pub fn opt_level(&mut self, opt_level: CraneliftOptLevel) -> &mut Self {
64
0
        self.opt_level = opt_level;
65
0
        self
66
0
    }
Unexecuted instantiation: <wasmer_compiler_cranelift::config::Cranelift>::opt_level
Unexecuted instantiation: <wasmer_compiler_cranelift::config::Cranelift>::opt_level
67
68
    /// Generates the ISA for the provided target
69
10.0k
    pub fn isa(&self, target: &Target) -> CodegenResult<Box<dyn TargetIsa>> {
70
10.0k
        let mut builder =
71
10.0k
            lookup(target.triple().clone()).expect("construct Cranelift ISA for triple");
72
10.0k
        // Cpu Features
73
10.0k
        let cpu_features = target.cpu_features();
74
10.0k
        if target.triple().architecture == Architecture::X86_64
75
10.0k
            && !cpu_features.contains(CpuFeature::SSE2)
76
        {
77
0
            panic!("x86 support requires SSE2");
78
10.0k
        }
79
10.0k
        if cpu_features.contains(CpuFeature::SSE3) {
80
10.0k
            builder.enable("has_sse3").expect("should be valid flag");
81
10.0k
        }
82
10.0k
        if cpu_features.contains(CpuFeature::SSSE3) {
83
10.0k
            builder.enable("has_ssse3").expect("should be valid flag");
84
10.0k
        }
85
10.0k
        if cpu_features.contains(CpuFeature::SSE41) {
86
10.0k
            builder.enable("has_sse41").expect("should be valid flag");
87
10.0k
        }
88
10.0k
        if cpu_features.contains(CpuFeature::SSE42) {
89
10.0k
            builder.enable("has_sse42").expect("should be valid flag");
90
10.0k
        }
91
10.0k
        if cpu_features.contains(CpuFeature::POPCNT) {
92
10.0k
            builder.enable("has_popcnt").expect("should be valid flag");
93
10.0k
        }
94
10.0k
        if cpu_features.contains(CpuFeature::AVX) {
95
10.0k
            builder.enable("has_avx").expect("should be valid flag");
96
10.0k
        }
97
10.0k
        if cpu_features.contains(CpuFeature::BMI1) {
98
10.0k
            builder.enable("has_bmi1").expect("should be valid flag");
99
10.0k
        }
100
10.0k
        if cpu_features.contains(CpuFeature::BMI2) {
101
10.0k
            builder.enable("has_bmi2").expect("should be valid flag");
102
10.0k
        }
103
10.0k
        if cpu_features.contains(CpuFeature::AVX2) {
104
10.0k
            builder.enable("has_avx2").expect("should be valid flag");
105
10.0k
        }
106
10.0k
        if cpu_features.contains(CpuFeature::AVX512DQ) {
107
0
            builder
108
0
                .enable("has_avx512dq")
109
0
                .expect("should be valid flag");
110
10.0k
        }
111
10.0k
        if cpu_features.contains(CpuFeature::AVX512VL) {
112
0
            builder
113
0
                .enable("has_avx512vl")
114
0
                .expect("should be valid flag");
115
10.0k
        }
116
10.0k
        if cpu_features.contains(CpuFeature::LZCNT) {
117
10.0k
            builder.enable("has_lzcnt").expect("should be valid flag");
118
10.0k
        }
119
120
10.0k
        builder.finish(self.flags(target))
121
10.0k
    }
<wasmer_compiler_cranelift::config::Cranelift>::isa
Line
Count
Source
69
10.0k
    pub fn isa(&self, target: &Target) -> CodegenResult<Box<dyn TargetIsa>> {
70
10.0k
        let mut builder =
71
10.0k
            lookup(target.triple().clone()).expect("construct Cranelift ISA for triple");
72
10.0k
        // Cpu Features
73
10.0k
        let cpu_features = target.cpu_features();
74
10.0k
        if target.triple().architecture == Architecture::X86_64
75
10.0k
            && !cpu_features.contains(CpuFeature::SSE2)
76
        {
77
0
            panic!("x86 support requires SSE2");
78
10.0k
        }
79
10.0k
        if cpu_features.contains(CpuFeature::SSE3) {
80
10.0k
            builder.enable("has_sse3").expect("should be valid flag");
81
10.0k
        }
82
10.0k
        if cpu_features.contains(CpuFeature::SSSE3) {
83
10.0k
            builder.enable("has_ssse3").expect("should be valid flag");
84
10.0k
        }
85
10.0k
        if cpu_features.contains(CpuFeature::SSE41) {
86
10.0k
            builder.enable("has_sse41").expect("should be valid flag");
87
10.0k
        }
88
10.0k
        if cpu_features.contains(CpuFeature::SSE42) {
89
10.0k
            builder.enable("has_sse42").expect("should be valid flag");
90
10.0k
        }
91
10.0k
        if cpu_features.contains(CpuFeature::POPCNT) {
92
10.0k
            builder.enable("has_popcnt").expect("should be valid flag");
93
10.0k
        }
94
10.0k
        if cpu_features.contains(CpuFeature::AVX) {
95
10.0k
            builder.enable("has_avx").expect("should be valid flag");
96
10.0k
        }
97
10.0k
        if cpu_features.contains(CpuFeature::BMI1) {
98
10.0k
            builder.enable("has_bmi1").expect("should be valid flag");
99
10.0k
        }
100
10.0k
        if cpu_features.contains(CpuFeature::BMI2) {
101
10.0k
            builder.enable("has_bmi2").expect("should be valid flag");
102
10.0k
        }
103
10.0k
        if cpu_features.contains(CpuFeature::AVX2) {
104
10.0k
            builder.enable("has_avx2").expect("should be valid flag");
105
10.0k
        }
106
10.0k
        if cpu_features.contains(CpuFeature::AVX512DQ) {
107
0
            builder
108
0
                .enable("has_avx512dq")
109
0
                .expect("should be valid flag");
110
10.0k
        }
111
10.0k
        if cpu_features.contains(CpuFeature::AVX512VL) {
112
0
            builder
113
0
                .enable("has_avx512vl")
114
0
                .expect("should be valid flag");
115
10.0k
        }
116
10.0k
        if cpu_features.contains(CpuFeature::LZCNT) {
117
10.0k
            builder.enable("has_lzcnt").expect("should be valid flag");
118
10.0k
        }
119
120
10.0k
        builder.finish(self.flags(target))
121
10.0k
    }
Unexecuted instantiation: <wasmer_compiler_cranelift::config::Cranelift>::isa
122
123
    /// Generates the flags for the compiler
124
10.0k
    pub fn flags(&self, target: &Target) -> settings::Flags {
125
10.0k
        let is_riscv = matches!(target.triple().architecture, Architecture::Riscv64(_));
126
10.0k
        let mut flags = settings::builder();
127
10.0k
128
10.0k
        // Enable probestack
129
10.0k
        flags
130
10.0k
            .enable("enable_probestack")
131
10.0k
            .expect("should be valid flag");
132
133
        // Only inline probestack is supported on AArch64
134
10.0k
        if matches!(target.triple().architecture, Architecture::Aarch64(_)) {
135
0
            flags
136
0
                .set("probestack_strategy", "inline")
137
0
                .expect("should be valid flag");
138
10.0k
        }
139
140
        // There are two possible traps for division, and this way
141
        // we get the proper one if code traps.
142
10.0k
        flags
143
10.0k
            .enable("avoid_div_traps")
144
10.0k
            .expect("should be valid flag");
145
10.0k
146
10.0k
        if self.enable_pic {
147
0
            flags.enable("is_pic").expect("should be a valid flag");
148
10.0k
        }
149
150
        // We set up libcall trampolines in engine-universal.
151
        // These trampolines are always reachable through short jumps.
152
10.0k
        flags
153
10.0k
            .enable("use_colocated_libcalls")
154
10.0k
            .expect("should be a valid flag");
155
156
        // Invert cranelift's default-on verification to instead default off.
157
10.0k
        let enable_verifier = if self.enable_verifier {
158
10.0k
            "true"
159
        } else {
160
0
            "false"
161
        };
162
10.0k
        flags
163
10.0k
            .set("enable_verifier", enable_verifier)
164
10.0k
            .expect("should be valid flag");
165
10.0k
        flags
166
10.0k
            .set("enable_safepoints", "true")
167
10.0k
            .expect("should be valid flag");
168
10.0k
169
10.0k
        flags
170
10.0k
            .set(
171
10.0k
                "opt_level",
172
10.0k
                match self.opt_level {
173
0
                    CraneliftOptLevel::None => "none",
174
10.0k
                    CraneliftOptLevel::Speed => "speed",
175
0
                    CraneliftOptLevel::SpeedAndSize => "speed_and_size",
176
                },
177
            )
178
10.0k
            .expect("should be valid flag");
179
10.0k
180
10.0k
        if is_riscv {
181
0
            flags
182
0
                .set("enable_simd", "false")
183
0
                .expect("should be valid flag");
184
10.0k
        } else {
185
10.0k
            flags
186
10.0k
                .set("enable_simd", "true")
187
10.0k
                .expect("should be valid flag");
188
10.0k
        }
189
190
10.0k
        let enable_nan_canonicalization = if self.enable_nan_canonicalization {
191
10.0k
            "true"
192
        } else {
193
0
            "false"
194
        };
195
10.0k
        flags
196
10.0k
            .set("enable_nan_canonicalization", enable_nan_canonicalization)
197
10.0k
            .expect("should be valid flag");
198
10.0k
199
10.0k
        settings::Flags::new(flags)
200
10.0k
    }
<wasmer_compiler_cranelift::config::Cranelift>::flags
Line
Count
Source
124
10.0k
    pub fn flags(&self, target: &Target) -> settings::Flags {
125
10.0k
        let is_riscv = matches!(target.triple().architecture, Architecture::Riscv64(_));
126
10.0k
        let mut flags = settings::builder();
127
10.0k
128
10.0k
        // Enable probestack
129
10.0k
        flags
130
10.0k
            .enable("enable_probestack")
131
10.0k
            .expect("should be valid flag");
132
133
        // Only inline probestack is supported on AArch64
134
10.0k
        if matches!(target.triple().architecture, Architecture::Aarch64(_)) {
135
0
            flags
136
0
                .set("probestack_strategy", "inline")
137
0
                .expect("should be valid flag");
138
10.0k
        }
139
140
        // There are two possible traps for division, and this way
141
        // we get the proper one if code traps.
142
10.0k
        flags
143
10.0k
            .enable("avoid_div_traps")
144
10.0k
            .expect("should be valid flag");
145
10.0k
146
10.0k
        if self.enable_pic {
147
0
            flags.enable("is_pic").expect("should be a valid flag");
148
10.0k
        }
149
150
        // We set up libcall trampolines in engine-universal.
151
        // These trampolines are always reachable through short jumps.
152
10.0k
        flags
153
10.0k
            .enable("use_colocated_libcalls")
154
10.0k
            .expect("should be a valid flag");
155
156
        // Invert cranelift's default-on verification to instead default off.
157
10.0k
        let enable_verifier = if self.enable_verifier {
158
10.0k
            "true"
159
        } else {
160
0
            "false"
161
        };
162
10.0k
        flags
163
10.0k
            .set("enable_verifier", enable_verifier)
164
10.0k
            .expect("should be valid flag");
165
10.0k
        flags
166
10.0k
            .set("enable_safepoints", "true")
167
10.0k
            .expect("should be valid flag");
168
10.0k
169
10.0k
        flags
170
10.0k
            .set(
171
10.0k
                "opt_level",
172
10.0k
                match self.opt_level {
173
0
                    CraneliftOptLevel::None => "none",
174
10.0k
                    CraneliftOptLevel::Speed => "speed",
175
0
                    CraneliftOptLevel::SpeedAndSize => "speed_and_size",
176
                },
177
            )
178
10.0k
            .expect("should be valid flag");
179
10.0k
180
10.0k
        if is_riscv {
181
0
            flags
182
0
                .set("enable_simd", "false")
183
0
                .expect("should be valid flag");
184
10.0k
        } else {
185
10.0k
            flags
186
10.0k
                .set("enable_simd", "true")
187
10.0k
                .expect("should be valid flag");
188
10.0k
        }
189
190
10.0k
        let enable_nan_canonicalization = if self.enable_nan_canonicalization {
191
10.0k
            "true"
192
        } else {
193
0
            "false"
194
        };
195
10.0k
        flags
196
10.0k
            .set("enable_nan_canonicalization", enable_nan_canonicalization)
197
10.0k
            .expect("should be valid flag");
198
10.0k
199
10.0k
        settings::Flags::new(flags)
200
10.0k
    }
Unexecuted instantiation: <wasmer_compiler_cranelift::config::Cranelift>::flags
201
}
202
203
impl CompilerConfig for Cranelift {
204
0
    fn enable_pic(&mut self) {
205
0
        self.enable_pic = true;
206
0
    }
Unexecuted instantiation: <wasmer_compiler_cranelift::config::Cranelift as wasmer_compiler::compiler::CompilerConfig>::enable_pic
Unexecuted instantiation: <wasmer_compiler_cranelift::config::Cranelift as wasmer_compiler::compiler::CompilerConfig>::enable_pic
Unexecuted instantiation: <wasmer_compiler_cranelift::config::Cranelift as wasmer_compiler::compiler::CompilerConfig>::enable_pic
Unexecuted instantiation: <wasmer_compiler_cranelift::config::Cranelift as wasmer_compiler::compiler::CompilerConfig>::enable_pic
Unexecuted instantiation: <wasmer_compiler_cranelift::config::Cranelift as wasmer_compiler::compiler::CompilerConfig>::enable_pic
207
208
5.00k
    fn enable_verifier(&mut self) {
209
5.00k
        self.enable_verifier = true;
210
5.00k
    }
Unexecuted instantiation: <wasmer_compiler_cranelift::config::Cranelift as wasmer_compiler::compiler::CompilerConfig>::enable_verifier
Unexecuted instantiation: <wasmer_compiler_cranelift::config::Cranelift as wasmer_compiler::compiler::CompilerConfig>::enable_verifier
Unexecuted instantiation: <wasmer_compiler_cranelift::config::Cranelift as wasmer_compiler::compiler::CompilerConfig>::enable_verifier
Unexecuted instantiation: <wasmer_compiler_cranelift::config::Cranelift as wasmer_compiler::compiler::CompilerConfig>::enable_verifier
<wasmer_compiler_cranelift::config::Cranelift as wasmer_compiler::compiler::CompilerConfig>::enable_verifier
Line
Count
Source
208
5.00k
    fn enable_verifier(&mut self) {
209
5.00k
        self.enable_verifier = true;
210
5.00k
    }
Unexecuted instantiation: <wasmer_compiler_cranelift::config::Cranelift as wasmer_compiler::compiler::CompilerConfig>::enable_verifier
Unexecuted instantiation: <wasmer_compiler_cranelift::config::Cranelift as wasmer_compiler::compiler::CompilerConfig>::enable_verifier
211
212
0
    fn canonicalize_nans(&mut self, enable: bool) {
213
0
        self.enable_nan_canonicalization = enable;
214
0
    }
Unexecuted instantiation: <wasmer_compiler_cranelift::config::Cranelift as wasmer_compiler::compiler::CompilerConfig>::canonicalize_nans
Unexecuted instantiation: <wasmer_compiler_cranelift::config::Cranelift as wasmer_compiler::compiler::CompilerConfig>::canonicalize_nans
Unexecuted instantiation: <wasmer_compiler_cranelift::config::Cranelift as wasmer_compiler::compiler::CompilerConfig>::canonicalize_nans
Unexecuted instantiation: <wasmer_compiler_cranelift::config::Cranelift as wasmer_compiler::compiler::CompilerConfig>::canonicalize_nans
Unexecuted instantiation: <wasmer_compiler_cranelift::config::Cranelift as wasmer_compiler::compiler::CompilerConfig>::canonicalize_nans
215
216
    /// Transform it into the compiler
217
5.00k
    fn compiler(self: Box<Self>) -> Box<dyn Compiler> {
218
5.00k
        Box::new(CraneliftCompiler::new(*self))
219
5.00k
    }
<wasmer_compiler_cranelift::config::Cranelift as wasmer_compiler::compiler::CompilerConfig>::compiler
Line
Count
Source
217
5.00k
    fn compiler(self: Box<Self>) -> Box<dyn Compiler> {
218
5.00k
        Box::new(CraneliftCompiler::new(*self))
219
5.00k
    }
Unexecuted instantiation: <wasmer_compiler_cranelift::config::Cranelift as wasmer_compiler::compiler::CompilerConfig>::compiler
220
221
    /// Pushes a middleware onto the back of the middleware chain.
222
0
    fn push_middleware(&mut self, middleware: Arc<dyn ModuleMiddleware>) {
223
0
        self.middlewares.push(middleware);
224
0
    }
Unexecuted instantiation: <wasmer_compiler_cranelift::config::Cranelift as wasmer_compiler::compiler::CompilerConfig>::push_middleware
Unexecuted instantiation: <wasmer_compiler_cranelift::config::Cranelift as wasmer_compiler::compiler::CompilerConfig>::push_middleware
225
}
226
227
impl Default for Cranelift {
228
5.00k
    fn default() -> Self {
229
5.00k
        Self::new()
230
5.00k
    }
Unexecuted instantiation: <wasmer_compiler_cranelift::config::Cranelift as core::default::Default>::default
Unexecuted instantiation: <wasmer_compiler_cranelift::config::Cranelift as core::default::Default>::default
Unexecuted instantiation: <wasmer_compiler_cranelift::config::Cranelift as core::default::Default>::default
Unexecuted instantiation: <wasmer_compiler_cranelift::config::Cranelift as core::default::Default>::default
<wasmer_compiler_cranelift::config::Cranelift as core::default::Default>::default
Line
Count
Source
228
5.00k
    fn default() -> Self {
229
5.00k
        Self::new()
230
5.00k
    }
Unexecuted instantiation: <wasmer_compiler_cranelift::config::Cranelift as core::default::Default>::default
Unexecuted instantiation: <wasmer_compiler_cranelift::config::Cranelift as core::default::Default>::default
231
}
232
233
impl From<Cranelift> for Engine {
234
0
    fn from(config: Cranelift) -> Self {
235
0
        EngineBuilder::new(config).engine()
236
0
    }
Unexecuted instantiation: <wasmer_compiler::engine::inner::Engine as core::convert::From<wasmer_compiler_cranelift::config::Cranelift>>::from
Unexecuted instantiation: <wasmer_compiler::engine::inner::Engine as core::convert::From<wasmer_compiler_cranelift::config::Cranelift>>::from
237
}