wasmer_compiler_cranelift/
config.rs1use crate::compiler::CraneliftCompiler;
2use cranelift_codegen::{
3 isa::{lookup, TargetIsa},
4 settings::{self, Configurable},
5 CodegenResult,
6};
7use std::sync::Arc;
8use wasmer_compiler::{
9 types::target::{Architecture, CpuFeature, Target},
10 Compiler, CompilerConfig, Engine, EngineBuilder, ModuleMiddleware,
11};
12
13#[non_exhaustive]
17#[derive(Clone, Debug)]
18pub enum CraneliftOptLevel {
19 None,
22 Speed,
24 SpeedAndSize,
27}
28
29#[derive(Debug, Clone)]
35pub struct Cranelift {
36 enable_nan_canonicalization: bool,
37 enable_verifier: bool,
38 enable_pic: bool,
39 opt_level: CraneliftOptLevel,
40 pub(crate) middlewares: Vec<Arc<dyn ModuleMiddleware>>,
42}
43
44impl Cranelift {
45 pub fn new() -> Self {
48 Self {
49 enable_nan_canonicalization: false,
50 enable_verifier: false,
51 opt_level: CraneliftOptLevel::Speed,
52 enable_pic: false,
53 middlewares: vec![],
54 }
55 }
56
57 pub fn canonicalize_nans(&mut self, enable: bool) -> &mut Self {
62 self.enable_nan_canonicalization = enable;
63 self
64 }
65
66 pub fn opt_level(&mut self, opt_level: CraneliftOptLevel) -> &mut Self {
68 self.opt_level = opt_level;
69 self
70 }
71
72 pub fn isa(&self, target: &Target) -> CodegenResult<Arc<dyn TargetIsa>> {
74 let mut builder =
75 lookup(target.triple().clone()).expect("construct Cranelift ISA for triple");
76 let cpu_features = target.cpu_features();
78 if target.triple().architecture == Architecture::X86_64
79 && !cpu_features.contains(CpuFeature::SSE2)
80 {
81 panic!("x86 support requires SSE2");
82 }
83 if cpu_features.contains(CpuFeature::SSE3) {
84 builder.enable("has_sse3").expect("should be valid flag");
85 }
86 if cpu_features.contains(CpuFeature::SSSE3) {
87 builder.enable("has_ssse3").expect("should be valid flag");
88 }
89 if cpu_features.contains(CpuFeature::SSE41) {
90 builder.enable("has_sse41").expect("should be valid flag");
91 }
92 if cpu_features.contains(CpuFeature::SSE42) {
93 builder.enable("has_sse42").expect("should be valid flag");
94 }
95 if cpu_features.contains(CpuFeature::POPCNT) {
96 builder.enable("has_popcnt").expect("should be valid flag");
97 }
98 if cpu_features.contains(CpuFeature::AVX) {
99 builder.enable("has_avx").expect("should be valid flag");
100 }
101 if cpu_features.contains(CpuFeature::BMI1) {
102 builder.enable("has_bmi1").expect("should be valid flag");
103 }
104 if cpu_features.contains(CpuFeature::BMI2) {
105 builder.enable("has_bmi2").expect("should be valid flag");
106 }
107 if cpu_features.contains(CpuFeature::AVX2) {
108 builder.enable("has_avx2").expect("should be valid flag");
109 }
110 if cpu_features.contains(CpuFeature::AVX512DQ) {
111 builder
112 .enable("has_avx512dq")
113 .expect("should be valid flag");
114 }
115 if cpu_features.contains(CpuFeature::AVX512VL) {
116 builder
117 .enable("has_avx512vl")
118 .expect("should be valid flag");
119 }
120 if cpu_features.contains(CpuFeature::LZCNT) {
121 builder.enable("has_lzcnt").expect("should be valid flag");
122 }
123
124 builder.finish(self.flags(target))
125 }
126
127 pub fn flags(&self, target: &Target) -> settings::Flags {
129 let mut flags = settings::builder();
130
131 flags
133 .enable("enable_probestack")
134 .expect("should be valid flag");
135
136 if matches!(target.triple().architecture, Architecture::Aarch64(_)) {
138 flags
139 .set("probestack_strategy", "inline")
140 .expect("should be valid flag");
141 }
142
143 if self.enable_pic {
144 flags.enable("is_pic").expect("should be a valid flag");
145 }
146
147 flags
150 .enable("use_colocated_libcalls")
151 .expect("should be a valid flag");
152
153 let enable_verifier = if self.enable_verifier {
155 "true"
156 } else {
157 "false"
158 };
159 flags
160 .set("enable_verifier", enable_verifier)
161 .expect("should be valid flag");
162 flags
163 .set("enable_safepoints", "true")
164 .expect("should be valid flag");
165
166 flags
167 .set(
168 "opt_level",
169 match self.opt_level {
170 CraneliftOptLevel::None => "none",
171 CraneliftOptLevel::Speed => "speed",
172 CraneliftOptLevel::SpeedAndSize => "speed_and_size",
173 },
174 )
175 .expect("should be valid flag");
176
177 let enable_nan_canonicalization = if self.enable_nan_canonicalization {
178 "true"
179 } else {
180 "false"
181 };
182 flags
183 .set("enable_nan_canonicalization", enable_nan_canonicalization)
184 .expect("should be valid flag");
185
186 settings::Flags::new(flags)
187 }
188}
189
190impl CompilerConfig for Cranelift {
191 fn enable_pic(&mut self) {
192 self.enable_pic = true;
193 }
194
195 fn enable_verifier(&mut self) {
196 self.enable_verifier = true;
197 }
198
199 fn canonicalize_nans(&mut self, enable: bool) {
200 self.enable_nan_canonicalization = enable;
201 }
202
203 fn compiler(self: Box<Self>) -> Box<dyn Compiler> {
205 Box::new(CraneliftCompiler::new(*self))
206 }
207
208 fn push_middleware(&mut self, middleware: Arc<dyn ModuleMiddleware>) {
210 self.middlewares.push(middleware);
211 }
212}
213
214impl Default for Cranelift {
215 fn default() -> Self {
216 Self::new()
217 }
218}
219
220impl From<Cranelift> for Engine {
221 fn from(config: Cranelift) -> Self {
222 EngineBuilder::new(config).engine()
223 }
224}