wasmer_engine_native_asml_fork/
engine.rs1use crate::NativeArtifact;
4use libloading::Library;
5use std::path::Path;
6use std::sync::Arc;
7use std::sync::Mutex;
8use wasmer_compiler::{CompileError, Target};
9#[cfg(feature = "compiler")]
10use wasmer_compiler::{Compiler, Triple};
11use wasmer_engine::{Artifact, DeserializeError, Engine, EngineId, Tunables};
12#[cfg(feature = "compiler")]
13use wasmer_types::Features;
14use wasmer_types::FunctionType;
15use wasmer_vm::{SignatureRegistry, VMSharedSignatureIndex};
16#[cfg(feature = "compiler")]
17use which::which;
18
19#[derive(Clone)]
21pub struct NativeEngine {
22 inner: Arc<Mutex<NativeEngineInner>>,
23 target: Arc<Target>,
25 engine_id: EngineId,
26}
27
28impl NativeEngine {
29 #[cfg(feature = "compiler")]
31 pub fn new(compiler: Box<dyn Compiler>, target: Target, features: Features) -> Self {
32 let host_target = Triple::host();
33 let is_cross_compiling = target.triple() != &host_target;
34
35 let linker = if is_cross_compiling {
36 which(Into::<&'static str>::into(Linker::Clang10))
37 .map(|_| Linker::Clang10)
38 .or_else(|_| {
39 which(Into::<&'static str>::into(Linker::Clang))
40 .map(|_| Linker::Clang)
41 })
42 .expect("Nor `clang-10` or `clang` has been found, at least one of them is required for the `NativeEngine`")
43 } else {
44 which(Into::<&'static str>::into(Linker::Gcc))
45 .map(|_| Linker::Gcc)
46 .expect("`gcc` has not been found, it is required for the `NativeEngine`")
47 };
48
49 Self {
50 inner: Arc::new(Mutex::new(NativeEngineInner {
51 compiler: Some(compiler),
52 signatures: SignatureRegistry::new(),
53 prefixer: None,
54 features,
55 is_cross_compiling,
56 linker,
57 libraries: vec![],
58 })),
59 target: Arc::new(target),
60 engine_id: EngineId::default(),
61 }
62 }
63
64 pub fn headless() -> Self {
78 Self {
79 inner: Arc::new(Mutex::new(NativeEngineInner {
80 #[cfg(feature = "compiler")]
81 compiler: None,
82 #[cfg(feature = "compiler")]
83 features: Features::default(),
84 signatures: SignatureRegistry::new(),
85 prefixer: None,
86 is_cross_compiling: false,
87 linker: Linker::None,
88 libraries: vec![],
89 })),
90 target: Arc::new(Target::default()),
91 engine_id: EngineId::default(),
92 }
93 }
94
95 pub fn set_deterministic_prefixer<F>(&mut self, prefixer: F)
106 where
107 F: Fn(&[u8]) -> String + Send + 'static,
108 {
109 let mut inner = self.inner_mut();
110 inner.prefixer = Some(Box::new(prefixer));
111 }
112
113 pub(crate) fn inner(&self) -> std::sync::MutexGuard<'_, NativeEngineInner> {
114 self.inner.lock().unwrap()
115 }
116
117 pub(crate) fn inner_mut(&self) -> std::sync::MutexGuard<'_, NativeEngineInner> {
118 self.inner.lock().unwrap()
119 }
120}
121
122impl Engine for NativeEngine {
123 fn target(&self) -> &Target {
125 &self.target
126 }
127
128 fn register_signature(&self, func_type: &FunctionType) -> VMSharedSignatureIndex {
130 let compiler = self.inner();
131 compiler.signatures().register(func_type)
132 }
133
134 fn lookup_signature(&self, sig: VMSharedSignatureIndex) -> Option<FunctionType> {
136 let compiler = self.inner();
137 compiler.signatures().lookup(sig)
138 }
139
140 fn validate(&self, binary: &[u8]) -> Result<(), CompileError> {
142 self.inner().validate(binary)
143 }
144
145 #[cfg(feature = "compiler")]
147 fn compile(
148 &self,
149 binary: &[u8],
150 tunables: &dyn Tunables,
151 ) -> Result<Arc<dyn Artifact>, CompileError> {
152 Ok(Arc::new(NativeArtifact::new(&self, binary, tunables)?))
153 }
154
155 #[cfg(not(feature = "compiler"))]
157 fn compile(
158 &self,
159 _binary: &[u8],
160 _tunables: &dyn Tunables,
161 ) -> Result<Arc<dyn Artifact>, CompileError> {
162 Err(CompileError::Codegen(
163 "The `NativeEngine` is operating in headless mode, so it cannot compile a module."
164 .to_string(),
165 ))
166 }
167
168 unsafe fn deserialize(&self, bytes: &[u8]) -> Result<Arc<dyn Artifact>, DeserializeError> {
170 Ok(Arc::new(NativeArtifact::deserialize(&self, &bytes)?))
171 }
172
173 unsafe fn deserialize_from_file(
176 &self,
177 file_ref: &Path,
178 ) -> Result<Arc<dyn Artifact>, DeserializeError> {
179 Ok(Arc::new(NativeArtifact::deserialize_from_file(
180 &self, &file_ref,
181 )?))
182 }
183
184 fn id(&self) -> &EngineId {
185 &self.engine_id
186 }
187
188 fn cloned(&self) -> Arc<dyn Engine + Send + Sync> {
189 Arc::new(self.clone())
190 }
191}
192
193#[derive(Clone, Copy)]
194pub(crate) enum Linker {
195 None,
196 Clang10,
197 Clang,
198 Gcc,
199}
200
201impl Into<&'static str> for Linker {
202 fn into(self) -> &'static str {
203 match self {
204 Self::None => "",
205 Self::Clang10 => "clang-10",
206 Self::Clang => "clang",
207 Self::Gcc => "gcc",
208 }
209 }
210}
211
212pub struct NativeEngineInner {
214 #[cfg(feature = "compiler")]
216 compiler: Option<Box<dyn Compiler>>,
217 #[cfg(feature = "compiler")]
219 features: Features,
220 signatures: SignatureRegistry,
223 prefixer: Option<Box<dyn Fn(&[u8]) -> String + Send>>,
227 is_cross_compiling: bool,
229 linker: Linker,
231 libraries: Vec<Library>,
233}
234
235impl NativeEngineInner {
236 #[cfg(feature = "compiler")]
238 pub fn compiler(&self) -> Result<&dyn Compiler, CompileError> {
239 if self.compiler.is_none() {
240 return Err(CompileError::Codegen("The `NativeEngine` is operating in headless mode, so it can only execute already compiled Modules.".to_string()));
241 }
242 Ok(&**self
243 .compiler
244 .as_ref()
245 .expect("Can't get compiler reference"))
246 }
247
248 #[cfg(feature = "compiler")]
249 pub(crate) fn get_prefix(&self, bytes: &[u8]) -> String {
250 if let Some(prefixer) = &self.prefixer {
251 prefixer(&bytes)
252 } else {
253 "".to_string()
254 }
255 }
256
257 #[cfg(feature = "compiler")]
258 pub(crate) fn features(&self) -> &Features {
259 &self.features
260 }
261
262 #[cfg(feature = "compiler")]
264 pub fn validate<'data>(&self, data: &'data [u8]) -> Result<(), CompileError> {
265 self.compiler()?.validate_module(self.features(), data)
266 }
267
268 #[cfg(not(feature = "compiler"))]
270 pub fn validate<'data>(&self, _data: &'data [u8]) -> Result<(), CompileError> {
271 Err(CompileError::Validate(
272 "The `NativeEngine` is not compiled with compiler support, which is required for validating".to_string(),
273 ))
274 }
275
276 pub fn signatures(&self) -> &SignatureRegistry {
278 &self.signatures
279 }
280
281 pub(crate) fn is_cross_compiling(&self) -> bool {
282 self.is_cross_compiling
283 }
284
285 pub(crate) fn linker(&self) -> Linker {
286 self.linker
287 }
288
289 pub(crate) fn add_library(&mut self, library: Library) {
290 self.libraries.push(library);
291 }
292}