1e069bdd3SNick Fitzgerald use super::*; 2c3a6060bSNick Fitzgerald use crate::ToWasmtimeResult as _; 3e069bdd3SNick Fitzgerald 4e069bdd3SNick Fitzgerald impl<'a> CodeBuilder<'a> { get_compile_time_builtins(&self) -> &HashMap<Cow<'a, str>, Cow<'a, [u8]>>5e069bdd3SNick Fitzgerald pub(crate) fn get_compile_time_builtins(&self) -> &HashMap<Cow<'a, str>, Cow<'a, [u8]>> { 6e069bdd3SNick Fitzgerald &self.compile_time_builtins 7e069bdd3SNick Fitzgerald } 8e069bdd3SNick Fitzgerald compose_compile_time_builtins<'b>( &self, main_wasm: &'b [u8], ) -> Result<Cow<'b, [u8]>>9e069bdd3SNick Fitzgerald pub(super) fn compose_compile_time_builtins<'b>( 10e069bdd3SNick Fitzgerald &self, 11e069bdd3SNick Fitzgerald main_wasm: &'b [u8], 12e069bdd3SNick Fitzgerald ) -> Result<Cow<'b, [u8]>> { 13e069bdd3SNick Fitzgerald if self.get_compile_time_builtins().is_empty() { 14e069bdd3SNick Fitzgerald return Ok(main_wasm.into()); 15e069bdd3SNick Fitzgerald } 16e069bdd3SNick Fitzgerald 17e069bdd3SNick Fitzgerald let imports = self.check_imports_for_compile_time_builtins(&main_wasm)?; 18e069bdd3SNick Fitzgerald if imports.is_empty() { 19e069bdd3SNick Fitzgerald drop(imports); 20e069bdd3SNick Fitzgerald return Ok(main_wasm.into()); 21e069bdd3SNick Fitzgerald } 22e069bdd3SNick Fitzgerald 23e069bdd3SNick Fitzgerald let tempdir = tempfile::TempDir::new().context("failed to create a temporary directory")?; 24e069bdd3SNick Fitzgerald let deps = tempdir.path().join("_deps"); 25e069bdd3SNick Fitzgerald std::fs::create_dir(&deps) 26e069bdd3SNick Fitzgerald .with_context(|| format!("failed to create directory: {}", deps.display()))?; 27e069bdd3SNick Fitzgerald 28e069bdd3SNick Fitzgerald let main_wasm_path = tempdir.path().join("_main.wasm"); 29e069bdd3SNick Fitzgerald std::fs::write(&main_wasm_path, &main_wasm) 30e069bdd3SNick Fitzgerald .with_context(|| format!("failed to write to file: {}", main_wasm_path.display()))?; 31e069bdd3SNick Fitzgerald 32e069bdd3SNick Fitzgerald let mut config = wasm_compose::config::Config::default(); 33e069bdd3SNick Fitzgerald for (name, bytes) in self.get_compile_time_builtins() { 34e069bdd3SNick Fitzgerald let name: &str = &*name; 35e069bdd3SNick Fitzgerald if !imports.contains(&name) { 36e069bdd3SNick Fitzgerald continue; 37e069bdd3SNick Fitzgerald } 38e069bdd3SNick Fitzgerald 39e069bdd3SNick Fitzgerald let mut path = deps.join(Path::new(name)); 40e069bdd3SNick Fitzgerald path.set_extension("wasm"); 41e069bdd3SNick Fitzgerald 42e069bdd3SNick Fitzgerald std::fs::write(&path, &bytes) 43e069bdd3SNick Fitzgerald .with_context(|| format!("failed to write to file: {}", path.display()))?; 44e069bdd3SNick Fitzgerald 45e069bdd3SNick Fitzgerald config 46e069bdd3SNick Fitzgerald .dependencies 47e069bdd3SNick Fitzgerald .insert(name.to_string(), wasm_compose::config::Dependency { path }); 48e069bdd3SNick Fitzgerald } 49e069bdd3SNick Fitzgerald 50e069bdd3SNick Fitzgerald let composer = wasm_compose::composer::ComponentComposer::new(&main_wasm_path, &config); 51c3a6060bSNick Fitzgerald let composed = composer.compose().to_wasmtime_result()?; 52e069bdd3SNick Fitzgerald Ok(composed.into()) 53e069bdd3SNick Fitzgerald } 54e069bdd3SNick Fitzgerald 55e069bdd3SNick Fitzgerald /// Check that the main Wasm doesn't import unsafe intrinsics, keeping the 56e069bdd3SNick Fitzgerald /// TCB to just the compile-time builtins' implementation. 57e069bdd3SNick Fitzgerald /// 58e069bdd3SNick Fitzgerald /// Returns the Wasm's top-level instance imports for `wasm-compose` 59e069bdd3SNick Fitzgerald /// configuration. check_imports_for_compile_time_builtins<'b>( &self, main_wasm: &'b [u8], ) -> Result<crate::hash_set::HashSet<&'b str>, Error>60e069bdd3SNick Fitzgerald fn check_imports_for_compile_time_builtins<'b>( 61e069bdd3SNick Fitzgerald &self, 62e069bdd3SNick Fitzgerald main_wasm: &'b [u8], 63e069bdd3SNick Fitzgerald ) -> Result<crate::hash_set::HashSet<&'b str>, Error> { 64e069bdd3SNick Fitzgerald let intrinsics_import = self.unsafe_intrinsics_import.as_deref().ok_or_else(|| { 65ff33e949SNick Fitzgerald format_err!( 66ff33e949SNick Fitzgerald "must configure the unsafe-intrinsics import when using compile-time builtins" 67ff33e949SNick Fitzgerald ) 68e069bdd3SNick Fitzgerald })?; 69e069bdd3SNick Fitzgerald 70e069bdd3SNick Fitzgerald let mut instance_imports = crate::hash_set::HashSet::new(); 71e069bdd3SNick Fitzgerald let parser = wasmparser::Parser::new(0); 72e069bdd3SNick Fitzgerald let mut level = 0; 73e069bdd3SNick Fitzgerald 74e069bdd3SNick Fitzgerald for payload in parser.parse_all(main_wasm) { 75e069bdd3SNick Fitzgerald match payload? { 76e069bdd3SNick Fitzgerald wasmparser::Payload::Version { .. } => { 77e069bdd3SNick Fitzgerald level += 1; 78e069bdd3SNick Fitzgerald } 79e069bdd3SNick Fitzgerald wasmparser::Payload::End(_) => { 80e069bdd3SNick Fitzgerald level -= 1; 81e069bdd3SNick Fitzgerald } 82e069bdd3SNick Fitzgerald wasmparser::Payload::ComponentImportSection(imports) if level == 1 => { 83e069bdd3SNick Fitzgerald for imp in imports.into_iter() { 84e069bdd3SNick Fitzgerald let imp = imp?; 85e069bdd3SNick Fitzgerald // Ideally we would simply choose a new import name that 86e069bdd3SNick Fitzgerald // doesn't conflict with the main Wasm's imports and 87e069bdd3SNick Fitzgerald // plumb that through to the compile-time builtins 88e069bdd3SNick Fitzgerald // regardless of the import name that they use, but 89e069bdd3SNick Fitzgerald // unfortunately the `wasm-compose` API is not powerful 90e069bdd3SNick Fitzgerald // enough for us to do all that. 91e069bdd3SNick Fitzgerald ensure!( 92e069bdd3SNick Fitzgerald imp.name.0 != intrinsics_import, 93e069bdd3SNick Fitzgerald "main Wasm cannot import the unsafe intrinsics (`{intrinsics_import}`) \ 94e069bdd3SNick Fitzgerald when using compile-time builtins" 95e069bdd3SNick Fitzgerald ); 96e069bdd3SNick Fitzgerald 97e069bdd3SNick Fitzgerald if let wasmparser::ComponentTypeRef::Instance(_) = imp.ty { 98e069bdd3SNick Fitzgerald instance_imports.insert(imp.name.0); 99e069bdd3SNick Fitzgerald } 100e069bdd3SNick Fitzgerald } 101e069bdd3SNick Fitzgerald } 102e069bdd3SNick Fitzgerald _ => {} 103e069bdd3SNick Fitzgerald } 104e069bdd3SNick Fitzgerald } 105e069bdd3SNick Fitzgerald 106e069bdd3SNick Fitzgerald Ok(instance_imports) 107e069bdd3SNick Fitzgerald } 108e069bdd3SNick Fitzgerald 109e069bdd3SNick Fitzgerald /// Define a compile-time builtin component, via its Wasm bytes. 110e069bdd3SNick Fitzgerald /// 111e069bdd3SNick Fitzgerald /// Compile-time builtins enable you to build safe, zero-copy, and (with 112e069bdd3SNick Fitzgerald /// [inlining][crate::Config::compiler_inlining]) 113e069bdd3SNick Fitzgerald /// zero-function-call-overhead Wasm APIs for accessing host data, buffers, 114e069bdd3SNick Fitzgerald /// and objects. 115e069bdd3SNick Fitzgerald /// 116e069bdd3SNick Fitzgerald /// A compile-time builtin is a component that is 117e069bdd3SNick Fitzgerald /// 118e069bdd3SNick Fitzgerald /// * authored by the host (Wasmtime embedder), 119e069bdd3SNick Fitzgerald /// 120e069bdd3SNick Fitzgerald /// * whose implementation (though not necessarily its interface!) is 121e069bdd3SNick Fitzgerald /// host-specific, 122e069bdd3SNick Fitzgerald /// 123e069bdd3SNick Fitzgerald /// * has access to unsafe intrinsics (and is therefore part of the host's 124e069bdd3SNick Fitzgerald /// [trusted compute base]), and 125e069bdd3SNick Fitzgerald /// 126e069bdd3SNick Fitzgerald /// * is linked into guest Wasm programs at compile-time. 127e069bdd3SNick Fitzgerald /// 128e069bdd3SNick Fitzgerald /// Any imports satisfied by a compile-time builtin during compilation will 129e069bdd3SNick Fitzgerald /// not show up in the resulting component's 130e069bdd3SNick Fitzgerald /// [imports][crate::component::types::Component::imports], and they can no 131e069bdd3SNick Fitzgerald /// longer be customized by a [`Linker`][crate::component::Linker] 132e069bdd3SNick Fitzgerald /// definition at instantiation time.[^0] 133e069bdd3SNick Fitzgerald /// 134e069bdd3SNick Fitzgerald /// [^0]: If linking compile-time builtins into a component at compile-time 135e069bdd3SNick Fitzgerald /// reminds you of [component composition], that is not a coincidence: 136e069bdd3SNick Fitzgerald /// component composition is used under the covers as part of compile-time 137e069bdd3SNick Fitzgerald /// builtins' implementation. 138e069bdd3SNick Fitzgerald /// 139e069bdd3SNick Fitzgerald /// Comparing compile-time builtins with 140e069bdd3SNick Fitzgerald /// [`Linker`][crate::component::Linker]s is informative: 141e069bdd3SNick Fitzgerald /// 142e069bdd3SNick Fitzgerald /// * Both mechanisms define APIs to satisfy a Wasm program's imports. 143e069bdd3SNick Fitzgerald /// 144e069bdd3SNick Fitzgerald /// * A `Linker` satisfies those imports at instantiation-time, while 145e069bdd3SNick Fitzgerald /// compile-time builtins do it during compilation. 146e069bdd3SNick Fitzgerald /// 147e069bdd3SNick Fitzgerald /// * APIs defined by a `Linker` are implemented in Rust, and hosts can 148e069bdd3SNick Fitzgerald /// build safe, sandboxed Wasm APIs on top of raw, un-sandboxed primitives 149e069bdd3SNick Fitzgerald /// via Rust's `unsafe`. APIs defined by compile-time builtins are 150e069bdd3SNick Fitzgerald /// implemented as Wasm components, and hosts can build safe, sandboxed 151e069bdd3SNick Fitzgerald /// Wasm APIs on top of raw, un-sandboxed primitives via [unsafe 152e069bdd3SNick Fitzgerald /// intrinsics][CodeBuilder::expose_unsafe_intrinsics]. 153e069bdd3SNick Fitzgerald /// 154e069bdd3SNick Fitzgerald /// * Imports satisfied via `Linker`-defined APIs are implemented with 155e069bdd3SNick Fitzgerald /// [PLT/GOT]-style function table lookups and indirect calls in the 156e069bdd3SNick Fitzgerald /// Wasm's compiled native code. On the other hand, Wasmtime implements 157e069bdd3SNick Fitzgerald /// calls to imports satisfied via compile-time builtins with direct calls 158e069bdd3SNick Fitzgerald /// in the Wasm's compiled native code. Wasmtime's compiler can also 159e069bdd3SNick Fitzgerald /// [inline][crate::Config::compiler_inlining] these direct calls, 160e069bdd3SNick Fitzgerald /// removing function call overheads and enabling further, cascading 161e069bdd3SNick Fitzgerald /// compiler optimizations. 162e069bdd3SNick Fitzgerald /// 163e069bdd3SNick Fitzgerald /// If you are familiar with Wasm on the Web, you can think of compile-time 164e069bdd3SNick Fitzgerald /// builtins as the rough equivalent of [the `js-string-builtins` proposal] 165e069bdd3SNick Fitzgerald /// but for arbitrary host-defined APIs in a Wasmtime embedding environment 166e069bdd3SNick Fitzgerald /// rather than JS string APIs in a Web browser environment. 167e069bdd3SNick Fitzgerald /// 168e069bdd3SNick Fitzgerald /// [trusted compute base]: https://en.wikipedia.org/wiki/Trusted_computing_base 169e069bdd3SNick Fitzgerald /// [the `js-string-builtins` proposal]: https://github.com/WebAssembly/js-string-builtins/blob/main/proposals/js-string-builtins/Overview.md 170e069bdd3SNick Fitzgerald /// [component composition]: https://component-model.bytecodealliance.org/composing-and-distributing/composing.html 171e069bdd3SNick Fitzgerald /// [PLT/GOT]: https://reverseengineering.stackexchange.com/a/1993 172e069bdd3SNick Fitzgerald /// 173e069bdd3SNick Fitzgerald /// # Safety 174e069bdd3SNick Fitzgerald /// 175e069bdd3SNick Fitzgerald /// Compile-time builtins are part of your [trusted compute base] and should 176e069bdd3SNick Fitzgerald /// be authored by trusted, first-party developers with extreme care. You 177e069bdd3SNick Fitzgerald /// should never use compile-time builtins authored by untrusted, 178e069bdd3SNick Fitzgerald /// third-party developers. 179e069bdd3SNick Fitzgerald /// 180e069bdd3SNick Fitzgerald /// Compile-time builtins are given access to Wasmtime's [unsafe 181e069bdd3SNick Fitzgerald /// intrinsics][CodeBuilder::expose_unsafe_intrinsics], and the same safety 182e069bdd3SNick Fitzgerald /// invariants and portability concerns apply. However, when compile-time 183e069bdd3SNick Fitzgerald /// builtins are defined on a `CodeBuilder`, unsafe intrinsics are *only* 184e069bdd3SNick Fitzgerald /// exposed to the compile-time builtins, and they are *not* exposed to the 185e069bdd3SNick Fitzgerald /// main guest Wasm program. This means that — assuming your compile-time 186e069bdd3SNick Fitzgerald /// builtins only exposing safe APIs, encapsulating the intrinsics' 187e069bdd3SNick Fitzgerald /// unsafety, and modulo bugs in your implementation of those safe APIs — 188e069bdd3SNick Fitzgerald /// that the main guest Wasm program is not part of your trusted compute 189e069bdd3SNick Fitzgerald /// base. 190e069bdd3SNick Fitzgerald /// 191e069bdd3SNick Fitzgerald /// # Example 192e069bdd3SNick Fitzgerald /// 193e069bdd3SNick Fitzgerald /// See the example in [CodeBuilder::expose_unsafe_intrinsics]. compile_time_builtins_binary( &mut self, name: impl Into<Cow<'a, str>>, wasm_bytes: impl Into<Cow<'a, [u8]>>, ) -> &mut Self194e069bdd3SNick Fitzgerald pub unsafe fn compile_time_builtins_binary( 195e069bdd3SNick Fitzgerald &mut self, 196e069bdd3SNick Fitzgerald name: impl Into<Cow<'a, str>>, 197e069bdd3SNick Fitzgerald wasm_bytes: impl Into<Cow<'a, [u8]>>, 198e069bdd3SNick Fitzgerald ) -> &mut Self { 199e069bdd3SNick Fitzgerald self.compile_time_builtins 200e069bdd3SNick Fitzgerald .insert(name.into(), wasm_bytes.into()); 201e069bdd3SNick Fitzgerald self 202e069bdd3SNick Fitzgerald } 203e069bdd3SNick Fitzgerald 204e069bdd3SNick Fitzgerald /// Equivalent of [`CodeBuilder::compile_time_builtins_binary`] that also 205e069bdd3SNick Fitzgerald /// accepts the WebAssembly text format. 206e069bdd3SNick Fitzgerald /// 207e069bdd3SNick Fitzgerald /// This method will configure the WebAssembly binary to be compiled and 208e069bdd3SNick Fitzgerald /// used to satisfy the `name` instance import. The input `wasm_bytes` may 209e069bdd3SNick Fitzgerald /// either be the wasm text format or the binary format. If the `wat` crate 210e069bdd3SNick Fitzgerald /// feature is enabled, which is enabled by default, then the text format 211e069bdd3SNick Fitzgerald /// will automatically be converted to the binary format. 212e069bdd3SNick Fitzgerald /// 213e069bdd3SNick Fitzgerald /// # Errors 214e069bdd3SNick Fitzgerald /// 215e069bdd3SNick Fitzgerald /// This method will also return an error if `wasm_bytes` is the wasm text 216e069bdd3SNick Fitzgerald /// format and the text syntax is not valid. 217e069bdd3SNick Fitzgerald /// 218e069bdd3SNick Fitzgerald /// # Safety 219e069bdd3SNick Fitzgerald /// 220e069bdd3SNick Fitzgerald /// See [`CodeBuilder::compile_time_builtins_binary`]. 221e069bdd3SNick Fitzgerald /// 222e069bdd3SNick Fitzgerald /// # Example 223e069bdd3SNick Fitzgerald /// 224e069bdd3SNick Fitzgerald /// See the example in [CodeBuilder::expose_unsafe_intrinsics], which uses 225e069bdd3SNick Fitzgerald /// compile-time builtins. 226*7a4f53a3SPiotr Sikora #[allow(unused_variables, reason = "`wasm_path` only used with `wat` feature")] compile_time_builtins_binary_or_text( &mut self, name: impl Into<Cow<'a, str>>, wasm_bytes: impl Into<Cow<'a, [u8]>>, wasm_path: Option<&Path>, ) -> Result<&mut Self>227e069bdd3SNick Fitzgerald pub unsafe fn compile_time_builtins_binary_or_text( 228e069bdd3SNick Fitzgerald &mut self, 229e069bdd3SNick Fitzgerald name: impl Into<Cow<'a, str>>, 230e069bdd3SNick Fitzgerald wasm_bytes: impl Into<Cow<'a, [u8]>>, 231e069bdd3SNick Fitzgerald wasm_path: Option<&Path>, 232e069bdd3SNick Fitzgerald ) -> Result<&mut Self> { 233e069bdd3SNick Fitzgerald let wasm_bytes = wasm_bytes.into(); 234e069bdd3SNick Fitzgerald 235e069bdd3SNick Fitzgerald #[cfg(feature = "wat")] 236e069bdd3SNick Fitzgerald if let Cow::Owned(wasm_bytes) = wat::parse_bytes(&wasm_bytes).map_err(|mut e| { 237e069bdd3SNick Fitzgerald if let Some(path) = wasm_path { 238e069bdd3SNick Fitzgerald e.set_path(path); 239e069bdd3SNick Fitzgerald } 240e069bdd3SNick Fitzgerald e 241e069bdd3SNick Fitzgerald })? { 242e069bdd3SNick Fitzgerald // SAFETY: Same as our unsafe contract. 243e069bdd3SNick Fitzgerald return Ok(unsafe { self.compile_time_builtins_binary(name, wasm_bytes) }); 244e069bdd3SNick Fitzgerald } 245e069bdd3SNick Fitzgerald 246e069bdd3SNick Fitzgerald // SAFETY: Same as our unsafe contract. 247e069bdd3SNick Fitzgerald Ok(unsafe { self.compile_time_builtins_binary(name, wasm_bytes) }) 248e069bdd3SNick Fitzgerald } 249e069bdd3SNick Fitzgerald 250e069bdd3SNick Fitzgerald /// Like [`CodeBuilder::compile_time_builtins_binary`], but reads the `file` 251e069bdd3SNick Fitzgerald /// specified for the bytes that will define the compile-time builtin. 252e069bdd3SNick Fitzgerald /// 253e069bdd3SNick Fitzgerald /// # Safety 254e069bdd3SNick Fitzgerald /// 255e069bdd3SNick Fitzgerald /// See [`CodeBuilder::compile_time_builtins_binary`]. 256e069bdd3SNick Fitzgerald /// 257e069bdd3SNick Fitzgerald /// # Example 258e069bdd3SNick Fitzgerald /// 259e069bdd3SNick Fitzgerald /// See the example in [CodeBuilder::expose_unsafe_intrinsics], which uses 260e069bdd3SNick Fitzgerald /// compile-time builtins. compile_time_builtins_binary_file( &mut self, name: impl Into<Cow<'a, str>>, file: &Path, ) -> Result<&mut Self>261e069bdd3SNick Fitzgerald pub unsafe fn compile_time_builtins_binary_file( 262e069bdd3SNick Fitzgerald &mut self, 263e069bdd3SNick Fitzgerald name: impl Into<Cow<'a, str>>, 264e069bdd3SNick Fitzgerald file: &Path, 265e069bdd3SNick Fitzgerald ) -> Result<&mut Self> { 266e069bdd3SNick Fitzgerald let wasm_bytes = std::fs::read(file) 267e069bdd3SNick Fitzgerald .with_context(|| format!("failed to read file: {}", file.display()))?; 268e069bdd3SNick Fitzgerald // SAFETY: Same as our unsafe contract. 269e069bdd3SNick Fitzgerald Ok(unsafe { self.compile_time_builtins_binary(name, wasm_bytes) }) 270e069bdd3SNick Fitzgerald } 271e069bdd3SNick Fitzgerald 272e069bdd3SNick Fitzgerald /// Equivalent of [`CodeBuilder::compile_time_builtins_binary_file`] that 273e069bdd3SNick Fitzgerald /// also accepts the WebAssembly text format. 274e069bdd3SNick Fitzgerald /// 275e069bdd3SNick Fitzgerald /// This method is will read the file at the given path and interpret the 276e069bdd3SNick Fitzgerald /// contents to determine if it's the Wasm text format or binary format. The 277e069bdd3SNick Fitzgerald /// file extension is not consulted. The text format is automatically 278e069bdd3SNick Fitzgerald /// converted to the binary format if the crate feature `wat` is active. 279e069bdd3SNick Fitzgerald /// 280e069bdd3SNick Fitzgerald /// # Errors 281e069bdd3SNick Fitzgerald /// 282e069bdd3SNick Fitzgerald /// In addition to the errors returned by 283e069bdd3SNick Fitzgerald /// [`CodeBuilder::compile_time_builtins_binary_file`] this may also fail if 284e069bdd3SNick Fitzgerald /// the text format is read and the syntax is invalid. 285e069bdd3SNick Fitzgerald /// 286e069bdd3SNick Fitzgerald /// # Safety 287e069bdd3SNick Fitzgerald /// 288e069bdd3SNick Fitzgerald /// See [`CodeBuilder::compile_time_builtins_binary`]. 289e069bdd3SNick Fitzgerald /// 290e069bdd3SNick Fitzgerald /// # Example 291e069bdd3SNick Fitzgerald /// 292e069bdd3SNick Fitzgerald /// See the example in [CodeBuilder::expose_unsafe_intrinsics], which uses 293e069bdd3SNick Fitzgerald /// compile-time builtins. compile_time_builtins_binary_or_text_file( &mut self, name: impl Into<Cow<'a, str>>, file: &Path, ) -> Result<&mut Self>294e069bdd3SNick Fitzgerald pub unsafe fn compile_time_builtins_binary_or_text_file( 295e069bdd3SNick Fitzgerald &mut self, 296e069bdd3SNick Fitzgerald name: impl Into<Cow<'a, str>>, 297e069bdd3SNick Fitzgerald file: &Path, 298e069bdd3SNick Fitzgerald ) -> Result<&mut Self> { 299e069bdd3SNick Fitzgerald #[cfg(feature = "wat")] 300e069bdd3SNick Fitzgerald { 301e069bdd3SNick Fitzgerald let wasm = wat::parse_file(file) 302e069bdd3SNick Fitzgerald .with_context(|| format!("error parsing file: {}", file.display()))?; 303e069bdd3SNick Fitzgerald // SAFETY: Same as our unsafe contract. 304e069bdd3SNick Fitzgerald Ok(unsafe { self.compile_time_builtins_binary(name, wasm) }) 305e069bdd3SNick Fitzgerald } 306e069bdd3SNick Fitzgerald 307e069bdd3SNick Fitzgerald #[cfg(not(feature = "wat"))] 308e069bdd3SNick Fitzgerald { 309e069bdd3SNick Fitzgerald // SAFETY: Same as our unsafe contract. 310e069bdd3SNick Fitzgerald unsafe { self.compile_time_builtins_binary_file(name, file) } 311e069bdd3SNick Fitzgerald } 312e069bdd3SNick Fitzgerald } 313e069bdd3SNick Fitzgerald } 314