Remove engine-dylib

This commit is contained in:
Manos Pitsidianakis
2022-05-10 12:32:26 +03:00
parent 699bd3f8ca
commit e9d54e130c
51 changed files with 140 additions and 2397 deletions

42
Cargo.lock generated
View File

@ -160,7 +160,7 @@ dependencies = [
"regex",
"rustc-hash",
"shlex",
"which 3.1.1",
"which",
]
[[package]]
@ -2796,7 +2796,6 @@ dependencies = [
"wasmer-compiler-singlepass",
"wasmer-derive",
"wasmer-engine",
"wasmer-engine-dylib",
"wasmer-engine-universal",
"wasmer-types",
"wasmer-vm",
@ -2826,7 +2825,6 @@ dependencies = [
"wasmer-compiler-cranelift",
"wasmer-compiler-llvm",
"wasmer-compiler-singlepass",
"wasmer-engine-dylib",
"wasmer-engine-universal",
"wasmer-middlewares",
"wasmprinter",
@ -2853,7 +2851,6 @@ dependencies = [
"wasmer-compiler-singlepass",
"wasmer-emscripten",
"wasmer-engine",
"wasmer-engine-dylib",
"wasmer-engine-staticlib",
"wasmer-engine-universal",
"wasmer-middlewares",
@ -2873,7 +2870,6 @@ dependencies = [
"thiserror",
"wasmer",
"wasmer-compiler-singlepass",
"wasmer-engine-dylib",
"wasmer-engine-universal",
]
@ -2900,7 +2896,6 @@ dependencies = [
"wasmer-compiler-singlepass",
"wasmer-emscripten",
"wasmer-engine",
"wasmer-engine-dylib",
"wasmer-engine-staticlib",
"wasmer-engine-universal",
"wasmer-types",
@ -3068,29 +3063,6 @@ dependencies = [
"wasmer-vm",
]
[[package]]
name = "wasmer-engine-dylib"
version = "2.3.0"
dependencies = [
"cfg-if 1.0.0",
"enum-iterator",
"enumset",
"leb128",
"libloading",
"object",
"rkyv",
"serde",
"tempfile",
"tracing",
"wasmer-artifact",
"wasmer-compiler",
"wasmer-engine",
"wasmer-object",
"wasmer-types",
"wasmer-vm",
"which 4.2.5",
]
[[package]]
name = "wasmer-engine-staticlib"
version = "2.3.0"
@ -3352,7 +3324,6 @@ dependencies = [
"wasmer-emscripten",
"wasmer-engine",
"wasmer-engine-dummy",
"wasmer-engine-dylib",
"wasmer-engine-staticlib",
"wasmer-engine-universal",
"wasmer-middlewares",
@ -3514,17 +3485,6 @@ dependencies = [
"libc",
]
[[package]]
name = "which"
version = "4.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c4fb54e6113b6a8772ee41c3404fb0301ac79604489467e0a9ce1f3e97c24ae"
dependencies = [
"either",
"lazy_static",
"libc",
]
[[package]]
name = "winapi"
version = "0.3.9"

View File

@ -18,7 +18,6 @@ wasmer-compiler-llvm = { version = "=2.3.0", path = "lib/compiler-llvm", optiona
wasmer-emscripten = { version = "=2.3.0", path = "lib/emscripten", optional = true }
wasmer-engine = { version = "=2.3.0", path = "lib/engine" }
wasmer-engine-universal = { version = "=2.3.0", path = "lib/engine-universal", optional = true }
wasmer-engine-dylib = { version = "=2.3.0", path = "lib/engine-dylib", optional = true }
wasmer-engine-staticlib = { version = "=2.3.0", path = "lib/engine-staticlib", optional = true }
wasmer-wasi = { version = "=2.3.0", path = "lib/wasi", optional = true }
wasmer-wast = { version = "=2.3.0", path = "tests/lib/wast", optional = true }
@ -43,7 +42,6 @@ members = [
"lib/emscripten",
"lib/engine",
"lib/engine-universal",
"lib/engine-dylib",
"lib/engine-staticlib",
"lib/object",
"lib/vfs",
@ -91,7 +89,6 @@ default = [
"wat",
"wast",
"universal",
"dylib",
"staticlib",
"cache",
"wasi",
@ -103,10 +100,6 @@ universal = [
"wasmer-engine-universal",
"engine",
]
dylib = [
"wasmer-engine-dylib",
"engine",
]
staticlib = [
"wasmer-engine-staticlib",
"engine",
@ -120,7 +113,6 @@ compiler = [
"wasmer/compiler",
"wasmer-compiler/translator",
"wasmer-engine-universal/compiler",
"wasmer-engine-dylib/compiler",
"wasmer-engine-staticlib/compiler",
]
singlepass = [
@ -148,10 +140,6 @@ test-llvm = [
"llvm",
]
test-dylib = [
"dylib",
"test-generator/test-dylib",
]
test-universal = [
"universal",
"test-generator/test-universal",
@ -178,11 +166,6 @@ name = "engine-universal"
path = "examples/engine_universal.rs"
required-features = ["cranelift"]
[[example]]
name = "engine-dylib"
path = "examples/engine_dylib.rs"
required-features = ["cranelift"]
[[example]]
name = "engine-headless"
path = "examples/engine_headless.rs"

View File

@ -13,29 +13,20 @@ SHELL=/usr/bin/env bash
# | Compiler Engine Platform Architecture libc |
# |------------|-----------|----------|--------------|-------|
# | Cranelift | Universal | Linux | amd64 | glibc |
# | LLVM | Dylib | Darwin | aarch64 | musl |
# | Singlepass | Staticlib | Windows | | |
# | LLVM | Staticlib | Darwin | aarch64 | musl |
# | Singlepass | | Windows | | |
# |------------|-----------|----------|--------------|-------|
#
# Here is what works and what doesn't:
#
# * Cranelift with the Universal engine works everywhere,
#
# * Cranelift with the Dylib engine works on Linux+Darwin/`amd64`, but
# it doesn't work on */`aarch64` or Windows/*.
#
# * LLVM with the Universal engine works on Linux+Darwin/`amd64`,
# but it doesn't work on */`aarch64` or Windows/*.
#
# * LLVM with the Dylib engine works on
# Linux+Darwin/`amd64`+`aarch64`, but it doesn't work on Windows/*.
#
# * Singlepass with the Universal engine works on Linux+Darwin/`amd64`, but
# it doesn't work on */`aarch64` or Windows/*.
#
# * Singlepass with the Dylib engine doesn't work because it doesn't
# know how to output object files for the moment.
#
# * Windows isn't tested on `aarch64`, that's why we consider it's not
# working, but it might possibly be.
@ -217,18 +208,6 @@ compilers_engines :=
ifeq ($(ENABLE_CRANELIFT), 1)
compilers_engines += cranelift-universal
ifneq (, $(filter 1, $(IS_WINDOWS) $(IS_DARWIN) $(IS_LINUX)))
ifeq ($(IS_AMD64), 1)
ifneq ($(LIBC), musl)
compilers_engines += cranelift-dylib
endif
else ifeq ($(IS_AARCH64), 1)
ifneq ($(LIBC), musl)
compilers_engines += cranelift-dylib
endif
endif
endif
endif
##
@ -239,10 +218,8 @@ ifeq ($(ENABLE_LLVM), 1)
ifneq (, $(filter 1, $(IS_WINDOWS) $(IS_DARWIN) $(IS_LINUX)))
ifeq ($(IS_AMD64), 1)
compilers_engines += llvm-universal
compilers_engines += llvm-dylib
else ifeq ($(IS_AARCH64), 1)
compilers_engines += llvm-universal
compilers_engines += llvm-dylib
endif
endif
endif
@ -284,7 +261,7 @@ capi_compilers_engines_exclude :=
# LLVM for the moment because it causes the linker to fail since LLVM is not statically linked.
# TODO: Reenable LLVM in C-API
capi_compiler_features := --features $(subst $(space),$(comma),$(filter-out llvm, $(compilers)))
capi_compilers_engines_exclude += llvm-universal llvm-dylib
capi_compilers_engines_exclude += llvm-universal
# We exclude singlepass-universal because it doesn't support multivalue (required in wasm-c-api tests)
capi_compilers_engines_exclude += singlepass-universal
@ -444,57 +421,45 @@ build-docs-capi: capi-setup
# when generating the documentation, we rename it to its
# crate's name. Then we restore the lib's name.
sed "$(SEDI)" -e 's/name = "wasmer" # ##lib.name##/name = "wasmer_c_api" # ##lib.name##/' lib/c-api/Cargo.toml
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) doc $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --no-deps --features wat,universal,staticlib,dylib,cranelift,wasi
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) doc $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --no-deps --features wat,universal,staticlib,cranelift,wasi
sed "$(SEDI)" -e 's/name = "wasmer_c_api" # ##lib.name##/name = "wasmer" # ##lib.name##/' lib/c-api/Cargo.toml
build-capi: capi-setup
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
--no-default-features --features wat,universal,dylib,staticlib,wasi,middlewares $(capi_compiler_features)
--no-default-features --features wat,universal,staticlib,wasi,middlewares $(capi_compiler_features)
build-capi-singlepass: capi-setup
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
--no-default-features --features wat,universal,dylib,staticlib,singlepass,wasi,middlewares
--no-default-features --features wat,universal,staticlib,singlepass,wasi,middlewares
build-capi-singlepass-universal: capi-setup
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
--no-default-features --features wat,universal,singlepass,wasi,middlewares
build-capi-singlepass-dylib: capi-setup
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
--no-default-features --features wat,dylib,singlepass,wasi,middlewares
build-capi-singlepass-staticlib: capi-setup
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
--no-default-features --features wat,staticlib,singlepass,wasi,middlewares
build-capi-cranelift: capi-setup
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
--no-default-features --features wat,universal,dylib,staticlib,cranelift,wasi,middlewares
--no-default-features --features wat,universal,staticlib,cranelift,wasi,middlewares
build-capi-cranelift-universal: capi-setup
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
--no-default-features --features wat,universal,cranelift,wasi,middlewares
build-capi-cranelift-dylib: capi-setup
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
--no-default-features --features wat,dylib,cranelift,wasi,middlewares
build-capi-cranelift-staticlib: capi-setup
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
--no-default-features --features wat,dylib,staticlib,cranelift,wasi,middlewares
--no-default-features --features wat,staticlib,cranelift,wasi,middlewares
build-capi-llvm: capi-setup
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
--no-default-features --features wat,universal,dylib,staticlib,llvm,wasi,middlewares
--no-default-features --features wat,universal,staticlib,llvm,wasi,middlewares
build-capi-llvm-universal: capi-setup
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
--no-default-features --features wat,universal,llvm,wasi,middlewares
build-capi-llvm-dylib: capi-setup
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
--no-default-features --features wat,dylib,llvm,wasi,middlewares
build-capi-llvm-staticlib: capi-setup
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
--no-default-features --features wat,staticlib,llvm,wasi,middlewares
@ -505,21 +470,17 @@ build-capi-headless-universal: capi-setup
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
--no-default-features --features universal,wasi
build-capi-headless-dylib: capi-setup
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
--no-default-features --features dylib,wasi
build-capi-headless-staticlib: capi-setup
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
--no-default-features --features staticlib,wasi
build-capi-headless-all: capi-setup
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
--no-default-features --features universal,dylib,staticlib,wasi
--no-default-features --features universal,staticlib,wasi
build-capi-headless-ios: capi-setup
RUSTFLAGS="${RUSTFLAGS}" cargo lipo --manifest-path lib/c-api/Cargo.toml --release \
--no-default-features --features dylib,wasi
--no-default-features --features wasi
#####
#
@ -554,21 +515,12 @@ test-js-wasi:
test-compilers-compat: $(foreach compiler,$(compilers),test-$(compiler))
test-singlepass-dylib:
$(CARGO_BINARY) test $(CARGO_TARGET) --release --tests $(compiler_features) -- singlepass::dylib
test-singlepass-universal:
$(CARGO_BINARY) test $(CARGO_TARGET) --release --tests $(compiler_features) -- singlepass::universal
test-cranelift-dylib:
$(CARGO_BINARY) test $(CARGO_TARGET) --release --tests $(compiler_features) -- cranelift::dylib
test-cranelift-universal:
$(CARGO_BINARY) test $(CARGO_TARGET) --release --tests $(compiler_features) -- cranelift::universal
test-llvm-dylib:
$(CARGO_BINARY) test $(CARGO_TARGET) --release --tests $(compiler_features) -- llvm::dylib
test-llvm-universal:
$(CARGO_BINARY) test $(CARGO_TARGET) --release --tests $(compiler_features) -- llvm::universal
@ -584,7 +536,7 @@ test-capi: build-capi package-capi $(foreach compiler_engine,$(capi_compilers_en
test-capi-crate-%:
WASMER_CAPI_CONFIG=$(shell echo $@ | sed -e s/test-capi-crate-//) $(CARGO_BINARY) test $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
--no-default-features --features wat,universal,dylib,staticlib,wasi,middlewares $(capi_compiler_features) -- --nocapture
--no-default-features --features wat,universal,staticlib,wasi,middlewares $(capi_compiler_features) -- --nocapture
test-capi-integration-%:
# Test the Wasmer C API tests for C

View File

@ -5,7 +5,6 @@ digraph dependencies {
n1 [label="wasmer-compiler", color=orange];
n5 [label="wasmer-engine", color=orange];
n6 [label="wasmer-engine-universal", color=orange];
n7 [label="wasmer-engine-dylib", color=orange];
n8 [label="wasmer-types", color=orange];
n9 [label="wasmer-vm", color=orange];
n10 [label="wasmer-c-api", color=orange];
@ -29,7 +28,6 @@ digraph dependencies {
color=brown;
n6 [label="wasmer-engine-universal", color=orange];
n7 [label="wasmer-engine-dylib", color=orange];
}
{

View File

@ -42,18 +42,6 @@
<path fill="none" stroke="orange" stroke-dasharray="5,2" d="M488.06,-373.25C467.43,-368.88 440.95,-362.59 418,-355 394.49,-347.23 369.06,-336.52 348.38,-327.2"/>
<polygon fill="orange" stroke="orange" points="349.79,-323.99 339.24,-323.02 346.88,-330.36 349.79,-323.99"/>
</g>
<!-- n7 -->
<g id="node5" class="node">
<title>n7</title>
<ellipse fill="none" stroke="orange" cx="102" cy="-306" rx="85.59" ry="18"/>
<text text-anchor="middle" x="102" y="-302.3" font-family="Times,serif" font-size="14.00">wasmer&#45;engine&#45;dylib</text>
</g>
<!-- n0&#45;&gt;n7 -->
<g id="edge13" class="edge">
<title>n0&#45;&gt;n7</title>
<path fill="none" stroke="orange" stroke-dasharray="5,2" d="M484.8,-378.93C410.73,-376.56 250.17,-369.84 197,-355 175.78,-349.08 153.72,-338.26 136.21,-328.39"/>
<polygon fill="orange" stroke="orange" points="137.9,-325.33 127.49,-323.35 134.39,-331.39 137.9,-325.33"/>
</g>
<!-- n2 -->
<g id="node13" class="node">
<title>n2</title>

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -236,24 +236,7 @@ example.
</details>
2. [**Dylib engine**][engine-dylib], explains what a Dylib engine
is, and how to set it up. The example completes itself with the
compilation of the Wasm module, its instantiation, and finally, by
calling an exported function.
_Keywords_: native, engine, shared library, dynamic library,
executable code.
<details>
<summary><em>Execute the example</em></summary>
```shell
$ cargo run --example engine-dylib --release --features "cranelift"
```
</details>
3. [**Headless engines**][engine-headless], explains what a headless
2. [**Headless engines**][engine-headless], explains what a headless
engine is, what problem it does solve, and what are the benefits of
it. The example completes itself with the instantiation of a
pre-compiled Wasm module, and finally, by calling an exported
@ -376,7 +359,6 @@ example.
[hello-world]: ./hello_world.rs
[engine-universal]: ./engine_universal.rs
[engine-dylib]: ./engine_dylib.rs
[engine-headless]: ./engine_headless.rs
[compiler-singlepass]: ./compiler_singlepass.rs
[compiler-cranelift]: ./compiler_cranelift.rs

View File

@ -22,7 +22,7 @@ use std::str::FromStr;
use wasmer::{wat2wasm, Module, RuntimeError, Store};
use wasmer_compiler::{CpuFeature, Target, Triple};
use wasmer_compiler_cranelift::Cranelift;
use wasmer_engine_dylib::Dylib;
use wasmer_engine_universal::Universal;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Let's declare the Wasm module with the text representation.
@ -67,13 +67,10 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
// Define the engine that will drive everything.
//
// In this case, the engine is `wasmer_engine_dylib` which means
// that a shared object is going to be generated.
//
// That's where we specify the target for the compiler.
//
// Use the Dylib engine.
let engine = Dylib::new(compiler_config)
// Use the Universal engine.
let engine = Universal::new(compiler_config)
// Here we go.
// Pass the target to the engine! The engine will share
// this information with the compiler.

View File

@ -20,67 +20,71 @@
use wasmer::{imports, wat2wasm, Instance, Module, Store, Value};
use wasmer_compiler_cranelift::Cranelift;
/*
use wasmer_engine_dylib::Dylib;
*/
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Let's declare the Wasm module with the text representation.
let wasm_bytes = wat2wasm(
r#"
(module
(type $sum_t (func (param i32 i32) (result i32)))
(func $sum_f (type $sum_t) (param $x i32) (param $y i32) (result i32)
local.get $x
local.get $y
i32.add)
(export "sum" (func $sum_f)))
"#
.as_bytes(),
)?;
/*
// Let's declare the Wasm module with the text representation.
let wasm_bytes = wat2wasm(
r#"
(module
(type $sum_t (func (param i32 i32) (result i32)))
(func $sum_f (type $sum_t) (param $x i32) (param $y i32) (result i32)
local.get $x
local.get $y
i32.add)
(export "sum" (func $sum_f)))
"#
.as_bytes(),
)?;
// Define a compiler configuration.
//
// In this situation, the compiler is
// `wasmer_compiler_cranelift`. The compiler is responsible to
// compile the Wasm module into executable code.
let compiler_config = Cranelift::default();
// Define a compiler configuration.
//
// In this situation, the compiler is
// `wasmer_compiler_cranelift`. The compiler is responsible to
// compile the Wasm module into executable code.
let compiler_config = Cranelift::default();
println!("Creating Dylib engine...");
// Define the engine that will drive everything.
//
// In this case, the engine is `wasmer_engine_dylib` which means
// that a shared object is going to be generated.
let engine = Dylib::new(compiler_config).engine();
println!("Creating Dylib engine...");
// Define the engine that will drive everything.
//
// In this case, the engine is `wasmer_engine_dylib` which means
// that a shared object is going to be generated.
let engine = Dylib::new(compiler_config).engine();
// Create a store, that holds the engine.
let store = Store::new(&engine);
// Create a store, that holds the engine.
let store = Store::new(&engine);
println!("Compiling module...");
// Here we go.
//
// Let's compile the Wasm module. It is at this step that the Wasm
// text is transformed into Wasm bytes (if necessary), and then
// compiled to executable code by the compiler, which is then
// stored into a shared object by the engine.
let module = Module::new(&store, wasm_bytes)?;
println!("Compiling module...");
// Here we go.
//
// Let's compile the Wasm module. It is at this step that the Wasm
// text is transformed into Wasm bytes (if necessary), and then
// compiled to executable code by the compiler, which is then
// stored into a shared object by the engine.
let module = Module::new(&store, wasm_bytes)?;
// Congrats, the Wasm module is compiled! Now let's execute it for
// the sake of having a complete example.
// Congrats, the Wasm module is compiled! Now let's execute it for
// the sake of having a complete example.
// Create an import object. Since our Wasm module didn't declare
// any imports, it's an empty object.
let import_object = imports! {};
// Create an import object. Since our Wasm module didn't declare
// any imports, it's an empty object.
let import_object = imports! {};
println!("Instantiating module...");
// And here we go again. Let's instantiate the Wasm module.
let instance = Instance::new(&module, &import_object)?;
println!("Instantiating module...");
// And here we go again. Let's instantiate the Wasm module.
let instance = Instance::new(&module, &import_object)?;
println!("Calling `sum` function...");
// The Wasm module exports a function called `sum`.
let sum = instance.exports.get_function("sum")?;
let results = sum.call(&[Value::I32(1), Value::I32(2)])?;
println!("Calling `sum` function...");
// The Wasm module exports a function called `sum`.
let sum = instance.exports.get_function("sum")?;
let results = sum.call(&[Value::I32(1), Value::I32(2)])?;
println!("Results: {:?}", results);
assert_eq!(results.to_vec(), vec![Value::I32(3)]);
println!("Results: {:?}", results);
assert_eq!(results.to_vec(), vec![Value::I32(3)]);
*/
Ok(())
}

View File

@ -8,10 +8,9 @@
//! What problem does it solve, and what does it mean?
//!
//! Once a Wasm module is compiled into executable code and stored
//! somewhere (e.g. in memory with the Universal engine, or in a
//! shared object file with the Dylib engine), the module can be
//! instantiated and executed. But imagine for a second the following
//! scenario:
//! somewhere (e.g. in memory with the Universal engine), the module
//! can be instantiated and executed. But imagine for a second the
//! following scenario:
//!
//! * Modules are compiled ahead of time, to be instantiated later
//! on.
@ -53,7 +52,7 @@ use wasmer::Module;
use wasmer::Store;
use wasmer::Value;
use wasmer_compiler_cranelift::Cranelift;
use wasmer_engine_dylib::Dylib;
use wasmer_engine_universal::Universal;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// First step, let's compile the Wasm module and serialize it.
@ -80,16 +79,9 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
// compile the Wasm module into executable code.
let compiler_config = Cranelift::default();
println!("Creating Dylib engine...");
println!("Creating univesral engine...");
// Define the engine that will drive everything.
//
// In this case, the engine is `wasmer_engine_dylib` which
// means that a shared object is going to be generated. So
// when we are going to serialize the compiled Wasm module, we
// are going to store it in a file with the `.so` extension
// for example (or `.dylib`, or `.dll` depending of the
// platform).
let engine = Dylib::new(compiler_config).engine();
let engine = Universal::new(compiler_config).engine();
// Create a store, that holds the engine.
let store = Store::new(&engine);
@ -110,9 +102,9 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
// Second step, deserialize the compiled Wasm module, and execute
// it, for example with Wasmer without a compiler.
{
println!("Creating headless Dylib engine...");
// We create a headless Dylib engine.
let engine = Dylib::headless().engine();
println!("Creating headless Universal engine...");
// We create a headless Universal engine.
let engine = Universal::headless().engine();
let store = Store::new(&engine);
println!("Deserializing module...");

View File

@ -17,49 +17,53 @@ use std::str::FromStr;
use wasmer::{wat2wasm, Module, RuntimeError, Store};
use wasmer_compiler::{CpuFeature, Target, Triple};
use wasmer_compiler_cranelift::Cranelift;
/*
use wasmer_engine_dylib::Dylib;
*/
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Let's declare the Wasm module with the text representation.
let wasm_bytes = wat2wasm(
r#"
(module
(type $sum_t (func (param i32 i32) (result i32)))
(func $sum_f (type $sum_t) (param $x i32) (param $y i32) (result i32)
local.get $x
local.get $y
i32.add)
(export "sum" (func $sum_f)))
"#
.as_bytes(),
)?;
/*
// Let's declare the Wasm module with the text representation.
let wasm_bytes = wat2wasm(
r#"
(module
(type $sum_t (func (param i32 i32) (result i32)))
(func $sum_f (type $sum_t) (param $x i32) (param $y i32) (result i32)
local.get $x
local.get $y
i32.add)
(export "sum" (func $sum_f)))
"#
.as_bytes(),
)?;
// Create a compiler for iOS
let compiler_config = Cranelift::default();
// Change it to `x86_64-apple-ios` if you want to target the iOS simulator
let triple = Triple::from_str("aarch64-apple-ios")
.map_err(|error| RuntimeError::new(error.to_string()))?;
// Create a compiler for iOS
let compiler_config = Cranelift::default();
// Change it to `x86_64-apple-ios` if you want to target the iOS simulator
let triple = Triple::from_str("aarch64-apple-ios")
.map_err(|error| RuntimeError::new(error.to_string()))?;
// Let's build the target.
let mut cpu_feature = CpuFeature::set();
cpu_feature.insert(CpuFeature::from_str("sse2")?);
let target = Target::new(triple, cpu_feature);
println!("Chosen target: {:?}", target);
// Let's build the target.
let mut cpu_feature = CpuFeature::set();
cpu_feature.insert(CpuFeature::from_str("sse2")?);
let target = Target::new(triple, cpu_feature);
println!("Chosen target: {:?}", target);
println!("Creating Dylib engine...");
let engine = Dylib::new(compiler_config).target(target).engine();
println!("Creating Dylib engine...");
let engine = Dylib::new(compiler_config).target(target).engine();
// Create a store, that holds the engine.
let store = Store::new(&engine);
// Create a store, that holds the engine.
let store = Store::new(&engine);
println!("Compiling module...");
// Let's compile the Wasm module.
let module = Module::new(&store, wasm_bytes)?;
// Here we go. Let's serialize the compiled Wasm module in a
// file.
println!("Serializing module...");
let dylib_file = Path::new("./sum.dylib");
module.serialize_to_file(dylib_file)?;
println!("Compiling module...");
// Let's compile the Wasm module.
let module = Module::new(&store, wasm_bytes)?;
// Here we go. Let's serialize the compiled Wasm module in a
// file.
println!("Serializing module...");
let dylib_file = Path::new("./sum.dylib");
module.serialize_to_file(dylib_file)?;
*/
Ok(())
}

View File

@ -17,7 +17,6 @@ wasmer-compiler-cranelift = { path = "../lib/compiler-cranelift", optional = tru
wasmer-compiler-llvm = { path = "../lib/compiler-llvm", optional = true }
wasmer-compiler-singlepass = { path = "../lib/compiler-singlepass", optional = true }
wasmer-engine-universal = { path = "../lib/engine-universal", optional = true }
wasmer-engine-dylib = { path = "../lib/engine-dylib", optional = true }
wasmer-middlewares = { path = "../lib/middlewares" }
wasmprinter = "0.2"
@ -26,7 +25,6 @@ cranelift = [ "wasmer-compiler-cranelift" ]
llvm = [ "wasmer-compiler-llvm" ]
singlepass = [ "wasmer-compiler-singlepass" ]
universal = [ "wasmer-engine-universal" ]
dylib = [ "wasmer-engine-dylib" ]
[[bin]]
name = "equivalence_universal"
@ -53,12 +51,7 @@ name = "metering"
path = "fuzz_targets/metering.rs"
required-features = ["universal", "cranelift"]
[[bin]]
name = "dylib_cranelift"
path = "fuzz_targets/dylib_cranelift.rs"
required-features = ["dylib", "cranelift"]
[[bin]]
name = "deterministic"
path = "fuzz_targets/deterministic.rs"
required-features = ["universal", "dylib", "cranelift", "llvm", "singlepass"]
required-features = ["universal", "cranelift", "llvm", "singlepass"]

View File

@ -6,7 +6,6 @@ use wasmer::{CompilerConfig, Engine, Module, Store};
use wasmer_compiler_cranelift::Cranelift;
use wasmer_compiler_llvm::LLVM;
use wasmer_compiler_singlepass::Singlepass;
use wasmer_engine_dylib::Dylib;
use wasmer_engine_universal::Universal;
#[derive(Arbitrary, Debug, Default, Copy, Clone)]
@ -51,11 +50,6 @@ fuzz_target!(|module: ConfiguredModule<NoImportsConfig>| {
Universal::new(compiler.clone()).engine(),
&wasm_bytes,
);
//compile_and_compare(
// "dylib-cranelift",
// Dylib::new(compiler).engine(),
// &wasm_bytes,
//);
let mut compiler = LLVM::default();
compiler.canonicalize_nans(true);
@ -65,7 +59,6 @@ fuzz_target!(|module: ConfiguredModule<NoImportsConfig>| {
Universal::new(compiler.clone()).engine(),
&wasm_bytes,
);
//compile_and_compare("dylib-llvm", Dylib::new(compiler).engine(), &wasm_bytes);
let compiler = Singlepass::default();
compile_and_compare(
@ -73,9 +66,4 @@ fuzz_target!(|module: ConfiguredModule<NoImportsConfig>| {
Universal::new(compiler.clone()).engine(),
&wasm_bytes,
);
//compile_and_compare(
// "dylib-singlepass",
// Dylib::new(compiler).engine(),
// &wasm_bytes,
//);
});

View File

@ -1,64 +0,0 @@
#![no_main]
use libfuzzer_sys::{arbitrary, arbitrary::Arbitrary, fuzz_target};
use wasm_smith::{Config, ConfiguredModule};
use wasmer::{imports, Instance, Module, Store};
use wasmer_compiler_cranelift::Cranelift;
use wasmer_engine_dylib::Dylib;
#[derive(Arbitrary, Debug, Default, Copy, Clone)]
struct NoImportsConfig;
impl Config for NoImportsConfig {
fn max_imports(&self) -> usize {
0
}
fn max_memory_pages(&self) -> u32 {
// https://github.com/wasmerio/wasmer/issues/2187
65535
}
fn allow_start_export(&self) -> bool {
false
}
}
#[derive(Arbitrary)]
struct WasmSmithModule(ConfiguredModule<NoImportsConfig>);
impl std::fmt::Debug for WasmSmithModule {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&wasmprinter::print_bytes(self.0.to_bytes()).unwrap())
}
}
fuzz_target!(|module: WasmSmithModule| {
let serialized = {
let wasm_bytes = module.0.to_bytes();
if let Ok(path) = std::env::var("DUMP_TESTCASE") {
use std::fs::File;
use std::io::Write;
let mut file = File::create(path).unwrap();
file.write_all(&wasm_bytes).unwrap();
return;
}
let compiler = Cranelift::default();
let store = Store::new(&Dylib::new(compiler).engine());
let module = Module::new(&store, &wasm_bytes).unwrap();
module.serialize().unwrap()
};
let engine = Dylib::headless().engine();
let store = Store::new(&engine);
let module = unsafe { Module::deserialize(&store, serialized.as_slice()) }.unwrap();
match Instance::new(&module, &imports! {}) {
Ok(_) => {}
Err(e) => {
let error_message = format!("{}", e);
if error_message.starts_with("RuntimeError: ")
&& error_message.contains("out of bounds")
{
return;
}
panic!("{}", e);
}
}
});

View File

@ -34,9 +34,6 @@ composed of a set of crates. We can group them as follows:
differ:
* `engine-universal` — stores the code in a custom file format, and
loads it in memory,
* `engine-dylib` — stores Position-Independent Code in a native
shared object library (`.dylib`, `.so`, `.dll`) and loads it with
Operating System shared library loader (via `dlopen`),
* `engine-staticlib` — stores executable code in a native static
object library, in addition to emitting a C header file, which
both can be linked against a sandboxed WebAssembly runtime

View File

@ -44,7 +44,6 @@ wasmer-compiler-singlepass = { path = "../compiler-singlepass", version = "=2.3.
wasmer-compiler-cranelift = { path = "../compiler-cranelift", version = "=2.3.0", optional = true }
wasmer-compiler-llvm = { path = "../compiler-llvm", version = "=2.3.0", optional = true }
wasmer-engine-universal = { path = "../engine-universal", version = "=2.3.0", optional = true }
wasmer-engine-dylib = { path = "../engine-dylib", version = "=2.3.0", optional = true }
# - Mandatory dependencies for `sys` on Windows.
[target.'cfg(all(not(target_arch = "wasm32"), target_os = "windows"))'.dependencies]
winapi = "0.3"
@ -93,7 +92,6 @@ compiler = [
"sys",
"wasmer-compiler/translator",
"wasmer-engine-universal/compiler",
"wasmer-engine-dylib/compiler",
]
singlepass = [
"compiler",
@ -126,19 +124,11 @@ engine = ["sys"]
"engine",
"wasmer-engine-universal",
]
dylib = [
"engine",
"wasmer-engine-dylib",
]
default-engine = []
default-universal = [
"default-engine",
"universal",
]
default-dylib = [
"default-engine",
"dylib",
]
# - Experimental / in-development features
experimental-reference-types-extern-ref = [
"sys",
@ -146,7 +136,6 @@ experimental-reference-types-extern-ref = [
]
# - Deprecated features.
jit = ["universal"]
native = ["dylib"]
# Features for `js`.
js = []
@ -157,4 +146,4 @@ wasm-types-polyfill = ["js", "wasmparser"]
js-serializable-module = []
[package.metadata.docs.rs]
features = ["compiler", "core", "cranelift", "default-compiler", "default-dylib", "default-engine", "dylib", "engine", "jit", "native", "singlepass", "sys", "sys-default", "universal"]
features = ["compiler", "core", "cranelift", "default-compiler", "default-engine", "engine", "jit", "native", "singlepass", "sys", "sys-default", "universal"]

View File

@ -49,8 +49,6 @@ Wasmer is not only fast, but also designed to be *highly customizable*:
compilation process and to store the generated executable code
somewhere, either:
* in-memory (with [`wasmer-engine-universal`]),
* in a native shared object file (with [`wasmer-engine-dylib`],
`.dylib`, `.so`, `.dll`), then load it with `dlopen`,
* in a native static object file (with [`wasmer-engine-staticlib`]),
in addition to emitting a C header file, which both can be linked
against a sandboxed WebAssembly runtime environment for the
@ -101,7 +99,6 @@ more](https://wasmerio.github.io/wasmer/crates/doc/wasmer/).
Made with ❤️ by the Wasmer team, for the community
[`wasmer-engine-universal`]: https://github.com/wasmerio/wasmer/tree/master/lib/engine-universal
[`wasmer-engine-dylib`]: https://github.com/wasmerio/wasmer/tree/master/lib/engine-dylib
[`wasmer-engine-staticlib`]: https://github.com/wasmerio/wasmer/tree/master/lib/engine-staticlib
[`wasmer-compiler-singlepass`]: https://github.com/wasmerio/wasmer/tree/master/lib/compiler-singlepass
[`wasmer-compiler-cranelift`]: https://github.com/wasmerio/wasmer/tree/master/lib/compiler-cranelift

View File

@ -77,8 +77,6 @@
//! compilation process and to store the generated executable code
//! somewhere, either:
//! * in-memory (with [`wasmer-engine-universal`]),
//! * in a native shared object file (with [`wasmer-engine-dylib`],
//! `.dylib`, `.so`, `.dll`), then load it with `dlopen`,
//! * in a native static object file (with [`wasmer-engine-staticlib`]),
//! in addition to emitting a C header file, which both can be linked
//! against a sandboxed WebAssembly runtime environment for the
@ -324,11 +322,7 @@
//! - `universal`
#![cfg_attr(feature = "universal", doc = "(enabled),")]
#![cfg_attr(not(feature = "universal"), doc = "(disabled),")]
//! enables [the Universal engine][`wasmer-engine-universal`],
//! - `dylib`
#![cfg_attr(feature = "dylib", doc = "(enabled),")]
#![cfg_attr(not(feature = "dylib"), doc = "(disabled),")]
//! enables [the Dylib engine][`wasmer-engine-dylib`].
//! enables [the Universal engine][`wasmer-engine-universal`].
//!
//! The features that set defaults come in sets that are mutually exclusive.
//!
@ -350,11 +344,7 @@
//! - `default-universal`
#![cfg_attr(feature = "default-universal", doc = "(enabled),")]
#![cfg_attr(not(feature = "default-universal"), doc = "(disabled),")]
//! set the Universal engine as the default,
//! - `default-dylib`
#![cfg_attr(feature = "default-dylib", doc = "(enabled),")]
#![cfg_attr(not(feature = "default-dylib"), doc = "(disabled),")]
//! set the Dylib engine as the default.
//! set the Universal engine as the default.
//!
#![cfg_attr(
feature = "js",
@ -434,7 +424,6 @@
//! [`wasmer-emscripten`]: https://docs.rs/wasmer-emscripten/
//! [wasmer-engine]: https://docs.rs/wasmer-engine/
//! [`wasmer-engine-universal`]: https://docs.rs/wasmer-engine-universal/
//! [`wasmer-engine-dylib`]: https://docs.rs/wasmer-engine-dylib/
//! [`wasmer-engine-staticlib`]: https://docs.rs/wasmer-engine-staticlib/
//! [`wasmer-compiler-singlepass`]: https://docs.rs/wasmer-compiler-singlepass/
//! [`wasmer-compiler-llvm`]: https://docs.rs/wasmer-compiler-llvm/

View File

@ -112,9 +112,6 @@ pub use wasmer_compiler_llvm::{LLVMOptLevel, LLVM};
#[cfg(feature = "universal")]
pub use wasmer_engine_universal::{Universal, UniversalArtifact, UniversalEngine};
#[cfg(feature = "dylib")]
pub use wasmer_engine_dylib::{Dylib, DylibArtifact, DylibEngine};
/// Version number of this crate.
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
@ -123,11 +120,6 @@ pub const VERSION: &str = env!("CARGO_PKG_VERSION");
#[deprecated(since = "2.0.0", note = "Please use the `universal` feature instead")]
pub type JIT = Universal;
/// The Deprecated Native Engine (please use `Dylib` instead)
#[cfg(feature = "native")]
#[deprecated(since = "2.0.0", note = "Please use the `native` feature instead")]
pub type Native = Dylib;
/// This type is deprecated, it has been replaced by TypedFunction.
#[deprecated(
since = "3.0.0",

View File

@ -121,9 +121,6 @@ impl Default for Store {
if #[cfg(feature = "default-universal")] {
wasmer_engine_universal::Universal::new(config)
.engine()
} else if #[cfg(feature = "default-dylib")] {
wasmer_engine_dylib::Dylib::new(config)
.engine()
} else {
compile_error!("No default engine chosen")
}

View File

@ -13,7 +13,6 @@ attributions of the project.
[`wasmer-engine-universal`]: https://github.com/wasmerio/wasmer/tree/master/lib/engine-universal
[`wasmer-engine-dylib`]: https://github.com/wasmerio/wasmer/tree/master/lib/engine-dylib
[`wasmer-engine-staticlib`]: https://github.com/wasmerio/wasmer/tree/master/lib/engine-staticlib
[`wasmer-engine-dummy`]: https://github.com/wasmerio/wasmer/tree/master/tests/lib/engine-dummy
[`wasmtime-api`]: https://crates.io/crates/wasmtime

View File

@ -29,7 +29,6 @@ wasmer-compiler-llvm = { version = "=2.3.0", path = "../compiler-llvm", optional
wasmer-emscripten = { version = "=2.3.0", path = "../emscripten", optional = true }
wasmer-engine = { version = "=2.3.0", path = "../engine" }
wasmer-engine-universal = { version = "=2.3.0", path = "../engine-universal", optional = true }
wasmer-engine-dylib = { version = "=2.3.0", path = "../engine-dylib", optional = true }
wasmer-engine-staticlib = { version = "=2.3.0", path = "../engine-staticlib", optional = true }
wasmer-middlewares = { version = "=2.3.0", path = "../middlewares", optional = true }
wasmer-wasi = { version = "=2.3.0", path = "../wasi", default-features = false, features = ["host-fs", "sys"], optional = true }
@ -66,10 +65,6 @@ universal = [
"wasmer-engine-universal",
"engine",
]
dylib = [
"wasmer-engine-dylib",
"engine",
]
staticlib = [
"wasmer-engine-staticlib",
"engine",
@ -77,7 +72,6 @@ staticlib = [
compiler = [
"wasmer-api/compiler",
"wasmer-engine-universal/compiler",
"wasmer-engine-dylib/compiler",
"wasmer-engine-staticlib/compiler"
]
singlepass = [
@ -95,10 +89,9 @@ llvm = [
# Deprecated features.
jit = ["universal"]
native = ["dylib"]
# TODO: Port this feature.
#emscripten = ["wasmer-emscripten"]
[build-dependencies]
cbindgen = "0.19"
cbindgen = "0.19"

View File

@ -13,8 +13,6 @@ use crate::error::update_last_error;
use cfg_if::cfg_if;
use std::sync::Arc;
use wasmer_api::Engine;
#[cfg(feature = "dylib")]
use wasmer_engine_dylib::Dylib;
#[cfg(feature = "staticlib")]
use wasmer_engine_staticlib::Staticlib;
#[cfg(feature = "universal")]
@ -70,10 +68,6 @@ pub enum wasmer_engine_t {
/// [`wasmer_engine_universal`] Rust crate.
UNIVERSAL = 0,
/// Variant to represent the Dylib engine. See the
/// [`wasmer_engine_dylib`] Rust crate.
DYLIB = 1,
/// Variant to represent the Staticlib engine. See the
/// [`wasmer_engine_staticlib`] Rust crate.
STATICLIB = 2,
@ -84,8 +78,6 @@ impl Default for wasmer_engine_t {
cfg_if! {
if #[cfg(feature = "universal")] {
Self::UNIVERSAL
} else if #[cfg(feature = "dylib")] {
Self::DYLIB
} else if #[cfg(feature = "staticlib")] {
Self::STATICLIB
} else {
@ -251,10 +243,6 @@ pub extern "C" fn wasm_config_set_compiler(
/// if (wasmer_is_engine_available(UNIVERSAL)) {
/// wasm_config_set_engine(config, UNIVERSAL);
/// }
/// // Or maybe the Dylib engine?
/// else if (wasmer_is_engine_available(DYLIB)) {
/// wasm_config_set_engine(config, DYLIB);
/// }
/// // OK, let's do not specify any particular engine.
///
/// // Create the engine.
@ -332,33 +320,6 @@ cfg_if! {
let engine: Arc<dyn Engine + Send + Sync> = Arc::new(Universal::headless().engine());
Box::new(wasm_engine_t { inner: engine })
}
} else if #[cfg(all(feature = "dylib", feature = "compiler"))] {
/// Creates a new Dylib engine with the default compiler.
///
/// # Example
///
/// See [`wasm_engine_delete`].
///
/// cbindgen:ignore
#[no_mangle]
pub extern "C" fn wasm_engine_new() -> Box<wasm_engine_t> {
let compiler_config: Box<dyn CompilerConfig> = get_default_compiler_config();
let engine: Arc<dyn Engine + Send + Sync> = Arc::new(Dylib::new(compiler_config).engine());
Box::new(wasm_engine_t { inner: engine })
}
} else if #[cfg(feature = "dylib")] {
/// Creates a new headless Dylib engine.
///
/// # Example
///
/// See [`wasm_engine_delete`].
///
/// cbindgen:ignore
#[no_mangle]
pub extern "C" fn wasm_engine_new() -> Box<wasm_engine_t> {
let engine: Arc<dyn Engine + Send + Sync> = Arc::new(Dylib::headless().engine());
Box::new(wasm_engine_t { inner: engine })
}
}
// There are currently no uses of the Staticlib engine + compiler from the C API.
// So if we get here, we default to headless mode regardless of if `compiler` is enabled.
@ -502,25 +463,6 @@ pub extern "C" fn wasm_engine_new_with_config(
}
}
},
wasmer_engine_t::DYLIB => {
cfg_if! {
if #[cfg(feature = "dylib")] {
let mut builder = Dylib::new(compiler_config);
if let Some(target) = config.target {
builder = builder.target(target.inner);
}
if let Some(features) = config.features {
builder = builder.features(features.inner);
}
Arc::new(builder.engine())
} else {
return return_with_error("Wasmer has not been compiled with the `dylib` feature.");
}
}
},
wasmer_engine_t::STATICLIB => {
cfg_if! {
// There are currently no uses of the Staticlib engine + compiler from the C API.
@ -565,25 +507,6 @@ pub extern "C" fn wasm_engine_new_with_config(
}
}
},
wasmer_engine_t::DYLIB => {
cfg_if! {
if #[cfg(feature = "dylib")] {
let mut builder = Dylib::headless();
if let Some(target) = config.target {
builder = builder.target(target.inner);
}
if let Some(features) = config.features {
builder = builder.features(features.inner);
}
Arc::new(builder.engine())
} else {
return return_with_error("Wasmer has not been compiled with the `dylib` feature.");
}
}
},
wasmer_engine_t::STATICLIB => {
cfg_if! {
if #[cfg(feature = "staticlib")] {

View File

@ -163,7 +163,6 @@ pub extern "C" fn wasmer_is_headless() -> bool {
pub extern "C" fn wasmer_is_engine_available(engine: wasmer_engine_t) -> bool {
match engine {
wasmer_engine_t::UNIVERSAL if cfg!(feature = "universal") => true,
wasmer_engine_t::DYLIB if cfg!(feature = "dylib") => true,
wasmer_engine_t::STATICLIB if cfg!(feature = "staticlib") => true,
_ => false,
}
@ -245,7 +244,6 @@ mod tests {
"0"
},
);
set_var("DYLIB", if cfg!(feature = "dylib") { "1" } else { "0" });
set_var(
"STATICLIB",
if cfg!(feature = "staticlib") {
@ -261,7 +259,6 @@ mod tests {
int main() {
assert(wasmer_is_engine_available(UNIVERSAL) == (getenv("UNIVERSAL")[0] == '1'));
assert(wasmer_is_engine_available(DYLIB) == (getenv("DYLIB")[0] == '1'));
assert(wasmer_is_engine_available(STATICLIB) == (getenv("STATICLIB")[0] == '1'));
return 0;
@ -270,7 +267,6 @@ mod tests {
.success();
remove_var("UNIVERSAL");
remove_var("DYLIB");
remove_var("STATICLIB");
}
}

View File

@ -34,9 +34,6 @@ wasm_engine_t *wasm_engine_new() {
if (strcmp(wasmer_test_engine, "universal") == 0) {
assert(wasmer_is_engine_available(UNIVERSAL));
wasm_config_set_engine(config, UNIVERSAL);
} else if (strcmp(wasmer_test_engine, "dylib") == 0) {
assert(wasmer_is_engine_available(DYLIB));
wasm_config_set_engine(config, DYLIB);
} else if (wasmer_test_engine) {
printf("Engine %s not recognized\n", wasmer_test_engine);
abort();

View File

@ -22,7 +22,6 @@ tempfile = "3"
rand = "0.8.3"
wasmer-compiler-singlepass = { path = "../compiler-singlepass", version = "=2.3.0" }
wasmer-engine-universal = { path = "../engine-universal", version = "=2.3.0" }
wasmer-engine-dylib = { path = "../engine-dylib", version = "=2.3.0" }
[features]
default = ["wasmer/js-serializable-module", "filesystem"]

View File

@ -7,7 +7,6 @@ use wasmer::{Module, Store};
use wasmer_cache::Cache;
use wasmer_cache::{FileSystemCache, Hash};
use wasmer_compiler_singlepass::Singlepass;
use wasmer_engine_dylib::Dylib;
use wasmer_engine_universal::Universal;
fn random_key() -> Hash {

View File

@ -33,7 +33,6 @@ wasmer-compiler-llvm = { version = "=2.3.0", path = "../compiler-llvm", optional
wasmer-emscripten = { version = "=2.3.0", path = "../emscripten", optional = true }
wasmer-engine = { version = "=2.3.0", path = "../engine" }
wasmer-engine-universal = { version = "=2.3.0", path = "../engine-universal", optional = true }
wasmer-engine-dylib = { version = "=2.3.0", path = "../engine-dylib", optional = true }
wasmer-engine-staticlib = { version = "=2.3.0", path = "../engine-staticlib", optional = true }
wasmer-vm = { version = "=2.3.0", path = "../vm" }
wasmer-wasi = { version = "=2.3.0", path = "../wasi", optional = true }
@ -66,7 +65,6 @@ default = [
"wat",
"wast",
"universal",
"dylib",
"staticlib",
"cache",
"wasi",
@ -77,10 +75,6 @@ universal = [
"wasmer-engine-universal",
"engine",
]
dylib = [
"wasmer-engine-dylib",
"engine",
]
staticlib = [
"wasmer-engine-staticlib",
"engine",
@ -94,7 +88,6 @@ wat = ["wasmer/wat"]
compiler = [
"wasmer-compiler/translator",
"wasmer-engine-universal/compiler",
"wasmer-engine-dylib/compiler",
"wasmer-engine-staticlib/compiler",
]
experimental-io-devices = [
@ -116,8 +109,7 @@ llvm = [
debug = ["fern", "log", "wasmer-wasi/logging"]
disable-all-logging = ["wasmer-wasi/disable-all-logging"]
headless = []
headless-minimal = ["headless", "disable-all-logging", "wasi", "dylib", "universal"]
headless-minimal = ["headless", "disable-all-logging", "wasi", "universal"]
# Deprecated features.
jit = ["universal"]
native = ["dylib"]

View File

@ -26,7 +26,6 @@ The Wasmer supports the following features:
* `wat` (default): support for executing WebAssembly text files.
* `wast`(default): support for running wast test files.
* `universal` (default): support for the [Universal engine].
* `dylib` (default): support for the [Dylib engine].
* `cache` (default): support or automatically caching compiled artifacts.
* `wasi` (default): support for [WASI].
* `experimental-io-devices`: support for experimental IO devices in WASI.
@ -36,7 +35,6 @@ The Wasmer supports the following features:
* `llvm`: support for the [LLVM compiler].
[Universal engine]: https://github.com/wasmerio/wasmer/tree/master/lib/engine-universal/
[Dylib engine]: https://github.com/wasmerio/wasmer/tree/master/lib/engine-dylib/
[WASI]: https://github.com/wasmerio/wasmer/tree/master/lib/wasi/
[Emscripten]: https://github.com/wasmerio/wasmer/tree/master/lib/emscripten/
[Singlepass compiler]: https://github.com/wasmerio/wasmer/tree/master/lib/compiler-singlepass/
@ -62,11 +60,11 @@ wasmer run myfile.wasm
Compile a WebAssembly file:
```bash
wasmer compile myfile.wasm -o myfile.so --dylib
wasmer compile myfile.wasm -o myfile.wasmu --universal
```
Run a compiled WebAssembly file (fastest):
```bash
wasmer run myfile.so
wasmer run myfile.wasmu
```

View File

@ -43,10 +43,6 @@ impl Compile {
target_triple: &Triple,
) -> Result<&'static str> {
Ok(match engine_type {
#[cfg(feature = "dylib")]
EngineType::Dylib => {
wasmer_engine_dylib::DylibArtifact::get_default_extension(target_triple)
}
#[cfg(feature = "universal")]
EngineType::Universal => {
wasmer_engine_universal::UniversalArtifact::get_default_extension(target_triple)
@ -55,7 +51,7 @@ impl Compile {
EngineType::Staticlib => {
wasmer_engine_staticlib::StaticlibArtifact::get_default_extension(target_triple)
}
#[cfg(not(all(feature = "dylib", feature = "universal", feature = "staticlib")))]
#[cfg(not(all(feature = "universal", feature = "staticlib")))]
_ => bail!("selected engine type is not compiled in"),
})
}

View File

@ -223,15 +223,6 @@ impl Run {
fn get_module(&self) -> Result<Module> {
let contents = std::fs::read(self.path.clone())?;
#[cfg(feature = "dylib")]
{
if wasmer_engine_dylib::DylibArtifact::is_deserializable(&contents) {
let engine = wasmer_engine_dylib::Dylib::headless().engine();
let store = Store::new(&engine);
let module = unsafe { Module::deserialize_from_file(&store, &self.path)? };
return Ok(module);
}
}
#[cfg(feature = "universal")]
{
if wasmer_engine_universal::UniversalArtifact::is_deserializable(&contents) {
@ -314,16 +305,8 @@ impl Run {
cache_dir_root.push(compiler_type.to_string());
let mut cache = FileSystemCache::new(cache_dir_root)?;
// Important: Dylib files need to have a `.dll` extension on
// Windows, otherwise they will not load, so we just add an
// extension always to make it easier to recognize as well.
#[allow(unreachable_patterns)]
let extension = match *engine_type {
#[cfg(feature = "dylib")]
EngineType::Dylib => {
wasmer_engine_dylib::DylibArtifact::get_default_extension(&Triple::host())
.to_string()
}
#[cfg(feature = "universal")]
EngineType::Universal => {
wasmer_engine_universal::UniversalArtifact::get_default_extension(&Triple::host())

View File

@ -23,27 +23,19 @@ pub struct StoreOptions {
compiler: CompilerOptions,
/// Use the Universal Engine.
#[structopt(long, conflicts_with_all = &["dylib", "staticlib", "jit", "native", "object_file"])]
#[structopt(long, conflicts_with_all = &["staticlib", "jit", "object_file"])]
universal: bool,
/// Use the Dylib Engine.
#[structopt(long, conflicts_with_all = &["universal", "staticlib", "jit", "native", "object_file"])]
dylib: bool,
/// Use the Staticlib Engine.
#[structopt(long, conflicts_with_all = &["universal", "dylib", "jit", "native", "object_file"])]
#[structopt(long, conflicts_with_all = &["universal", "jit", "object_file"])]
staticlib: bool,
/// Use the JIT (Universal) Engine.
#[structopt(long, hidden = true, conflicts_with_all = &["universal", "dylib", "staticlib", "native", "object_file"])]
#[structopt(long, hidden = true, conflicts_with_all = &["universal", "staticlib", "object_file"])]
jit: bool,
/// Use the Native (Dylib) Engine.
#[structopt(long, hidden = true, conflicts_with_all = &["universal", "dylib", "staticlib", "jit", "object_file"])]
native: bool,
/// Use the ObjectFile (Staticlib) Engine.
#[structopt(long, hidden = true, conflicts_with_all = &["universal", "dylib", "staticlib", "jit", "native"])]
#[structopt(long, hidden = true, conflicts_with_all = &["universal", "staticlib", "jit"])]
object_file: bool,
}
@ -150,13 +142,6 @@ impl CompilerOptions {
.target(target)
.engine(),
),
#[cfg(feature = "dylib")]
EngineType::Dylib => Box::new(
wasmer_engine_dylib::Dylib::new(compiler_config)
.target(target)
.features(features)
.engine(),
),
#[cfg(feature = "staticlib")]
EngineType::Staticlib => Box::new(
wasmer_engine_staticlib::Staticlib::new(compiler_config)
@ -164,7 +149,7 @@ impl CompilerOptions {
.features(features)
.engine(),
),
#[cfg(not(all(feature = "universal", feature = "dylib", feature = "staticlib")))]
#[cfg(not(all(feature = "universal", feature = "staticlib")))]
engine => bail!(
"The `{}` engine is not included in this binary.",
engine.to_string()
@ -356,8 +341,6 @@ impl ToString for CompilerType {
pub enum EngineType {
/// Universal Engine
Universal,
/// Dylib Engine
Dylib,
/// Static Engine
Staticlib,
}
@ -366,7 +349,6 @@ impl ToString for EngineType {
fn to_string(&self) -> String {
match self {
Self::Universal => "universal".to_string(),
Self::Dylib => "dylib".to_string(),
Self::Staticlib => "staticlib".to_string(),
}
}
@ -410,16 +392,12 @@ impl StoreOptions {
fn get_engine(&self) -> Result<EngineType> {
if self.universal || self.jit {
Ok(EngineType::Universal)
} else if self.dylib || self.native {
Ok(EngineType::Dylib)
} else if self.staticlib || self.object_file {
Ok(EngineType::Staticlib)
} else {
// Auto mode, we choose the best engine for that platform
if cfg!(feature = "universal") {
Ok(EngineType::Universal)
} else if cfg!(feature = "dylib") {
Ok(EngineType::Dylib)
} else if cfg!(feature = "staticlib") {
Ok(EngineType::Staticlib)
} else {
@ -439,13 +417,11 @@ impl StoreOptions {
EngineType::Universal => {
Arc::new(wasmer_engine_universal::Universal::headless().engine())
}
#[cfg(feature = "dylib")]
EngineType::Dylib => Arc::new(wasmer_engine_dylib::Dylib::headless().engine()),
#[cfg(feature = "staticlib")]
EngineType::Staticlib => {
Arc::new(wasmer_engine_staticlib::Staticlib::headless().engine())
}
#[cfg(not(all(feature = "universal", feature = "dylib", feature = "staticlib")))]
#[cfg(not(all(feature = "universal", feature = "staticlib")))]
engine => bail!(
"The `{}` engine is not included in this binary.",
engine.to_string()

View File

@ -135,7 +135,7 @@ impl Cranelift {
flags.enable("is_pic").expect("should be a valid flag");
}
// We set up libcall trampolines in engine-dylib and engine-universal.
// We set up libcall trampolines in engine-universal.
// These trampolines are always reachable through short jumps.
flags
.enable("use_colocated_libcalls")

View File

@ -1,38 +0,0 @@
[package]
name = "wasmer-engine-dylib"
version = "2.3.0"
description = "Wasmer Dylib Engine"
categories = ["wasm"]
keywords = ["wasm", "webassembly", "engine", "dylib"]
authors = ["Wasmer Engineering Team <engineering@wasmer.io>"]
repository = "https://github.com/wasmerio/wasmer"
license = "MIT"
readme = "README.md"
edition = "2018"
[dependencies]
wasmer-artifact = { path = "../artifact", version = "=2.3.0" }
wasmer-types = { path = "../types", version = "=2.3.0" }
wasmer-compiler = { path = "../compiler", version = "=2.3.0" }
wasmer-vm = { path = "../vm", version = "=2.3.0" }
wasmer-engine = { path = "../engine", version = "=2.3.0" }
wasmer-object = { path = "../object", version = "=2.3.0" }
serde = { version = "1.0", features = ["derive", "rc"] }
cfg-if = "1.0"
tracing = { version = "0.1", features = ["log"] }
leb128 = "0.2"
libloading = "0.7"
tempfile = "3.1"
which = "4.0"
rkyv = { version = "0.7.38", features = ["indexmap"] }
enumset = "1.0"
enum-iterator = "0.7.0"
object = { version = "0.28.3", default-features = false, features = ["write"] }
[features]
# Enable the `compiler` feature if you want the engine to compile
# and not be only on headless mode.
compiler = ["wasmer-compiler/translator"]
[badges]
maintenance = { status = "actively-developed" }

View File

@ -1,60 +0,0 @@
# `wasmer-engine-dylib` [![Build Status](https://github.com/wasmerio/wasmer/workflows/build/badge.svg?style=flat-square)](https://github.com/wasmerio/wasmer/actions?query=workflow%3Abuild) [![Join Wasmer Slack](https://img.shields.io/static/v1?label=Slack&message=join%20chat&color=brighgreen&style=flat-square)](https://slack.wasmer.io) [![MIT License](https://img.shields.io/github/license/wasmerio/wasmer.svg?style=flat-square)](https://github.com/wasmerio/wasmer/blob/master/LICENSE)
The Wasmer Dylib engine is usable with any compiler implementation
based on [`wasmer-compiler`] that is able to emit
[Position-Independent Code][PIC] (PIC).
After the compiler generates the machine code for the functions, the
Dylib Engine generates a shared object file and links it via [`dlsym`]
so it can be usable by the [`wasmer`] API.
This allows Wasmer to achieve *blazing fast* **native startup times**.
*Note: you can find a [full working example using the Dylib engine
here][example].*
### Difference with `wasmer-engine-universal`
The Dylib Engine and Universal Engine mainly differ on how the Modules
are loaded/stored. Using the same compilers, both will have the same
runtime speed.
However, the Dylib Engine uses the Operating System shared library
loader (via `dlopen`) and as such is able to achieve a much faster
startup time when deserializing a serialized `Module`.
## Requirements
The `wasmer-engine-dylib` crate requires a linker available on
your system to generate the shared object file.
We recommend having [`gcc`] or [`clang`] installed.
> Note: when **cross-compiling** to other targets, `clang` will be the
> default command used for compiling.
You can install LLVM (that provides `clang`) easily on your
Debian-like system via this command:
```bash
bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)"
```
Or in macOS:
```bash
brew install llvm
```
Or via any of the [pre-built binaries that LLVM
offers][llvm-pre-built].
[`wasmer-compiler`]: https://github.com/wasmerio/wasmer/tree/master/lib/compiler
[PIC]: https://en.wikipedia.org/wiki/Position-independent_code
[`dlsym`]: https://www.freebsd.org/cgi/man.cgi?query=dlsym
[`wasmer`]: https://github.com/wasmerio/wasmer/tree/master/lib/api
[example]: https://github.com/wasmerio/wasmer/blob/master/examples/engine_dylib.rs
[`gcc`]: https://gcc.gnu.org/
[`clang`]: https://clang.llvm.org/
[llvm-pre-built]: https://releases.llvm.org/download.html

View File

@ -1,897 +0,0 @@
//! Define `DylibArtifact` to allow compiling and instantiating
//! to be done as separate steps.
use crate::engine::{DylibEngine, DylibEngineInner};
use crate::serialize::ModuleMetadata;
use crate::trampoline::{emit_trampolines, fill_trampoline_table, WASMER_TRAMPOLINES_SYMBOL};
use enumset::EnumSet;
use libloading::{Library, Symbol as LibrarySymbol};
use object::{write::CoffExportStyle, BinaryFormat};
use std::error::Error;
use std::fs::{self, File};
use std::io::{Read, Write};
use std::path::{Path, PathBuf};
#[cfg(feature = "compiler")]
use std::process::Command;
use std::sync::{Arc, Mutex};
use tempfile::NamedTempFile;
use tracing::log::error;
#[cfg(feature = "compiler")]
use tracing::trace;
use wasmer_artifact::ArtifactCreate;
use wasmer_compiler::{
Architecture, CompileError, CompiledFunctionFrameInfo, CpuFeature, Features,
FunctionAddressMap, OperatingSystem, Symbol, SymbolRegistry, Triple,
};
#[cfg(feature = "compiler")]
use wasmer_compiler::{
CompileModuleInfo, Compiler, FunctionBodyData, ModuleEnvironment, ModuleMiddlewareChain,
ModuleTranslationState,
};
use wasmer_engine::{
register_frame_info, Artifact, DeserializeError, FunctionExtent, GlobalFrameInfoRegistration,
InstantiationError, MetadataHeader, SerializeError,
};
#[cfg(feature = "compiler")]
use wasmer_engine::{Engine, Tunables};
#[cfg(feature = "compiler")]
use wasmer_object::{emit_compilation, emit_data, get_object_for_target};
use wasmer_types::entity::{BoxedSlice, PrimaryMap};
#[cfg(feature = "compiler")]
use wasmer_types::DataInitializer;
use wasmer_types::{
FunctionIndex, LocalFunctionIndex, MemoryIndex, ModuleInfo, OwnedDataInitializer,
SignatureIndex, TableIndex,
};
use wasmer_vm::{
FuncDataRegistry, FunctionBodyPtr, MemoryStyle, TableStyle, VMFunctionBody,
VMSharedSignatureIndex, VMTrampoline,
};
/// A compiled Wasm module, ready to be instantiated.
pub struct DylibArtifact {
dylib_path: PathBuf,
is_temporary: bool,
metadata: ModuleMetadata,
finished_functions: BoxedSlice<LocalFunctionIndex, FunctionBodyPtr>,
finished_function_call_trampolines: BoxedSlice<SignatureIndex, VMTrampoline>,
finished_dynamic_function_trampolines: BoxedSlice<FunctionIndex, FunctionBodyPtr>,
func_data_registry: Arc<FuncDataRegistry>,
signatures: BoxedSlice<SignatureIndex, VMSharedSignatureIndex>,
frame_info_registration: Mutex<Option<GlobalFrameInfoRegistration>>,
}
impl Drop for DylibArtifact {
fn drop(&mut self) {
if self.is_temporary {
if let Err(err) = std::fs::remove_file(&self.dylib_path) {
error!("cannot delete the temporary dylib artifact: {}", err);
}
}
}
}
fn to_compile_error(err: impl Error) -> CompileError {
CompileError::Codegen(err.to_string())
}
const WASMER_METADATA_SYMBOL: &[u8] = b"WASMER_METADATA";
impl DylibArtifact {
// Mach-O header in iOS/Mac
#[allow(dead_code)]
const MAGIC_HEADER_MH_CIGAM_64: &'static [u8] = &[207, 250, 237, 254];
// ELF Magic header for Linux (32 bit)
#[allow(dead_code)]
const MAGIC_HEADER_ELF_32: &'static [u8] = &[0x7f, b'E', b'L', b'F', 1];
// ELF Magic header for Linux (64 bit)
#[allow(dead_code)]
const MAGIC_HEADER_ELF_64: &'static [u8] = &[0x7f, b'E', b'L', b'F', 2];
// COFF Magic header for Windows (64 bit)
#[allow(dead_code)]
const MAGIC_HEADER_COFF_64: &'static [u8] = &[b'M', b'Z'];
/// Check if the provided bytes look like `DylibArtifact`.
///
/// This means, if the bytes look like a shared object file in the target
/// system.
pub fn is_deserializable(bytes: &[u8]) -> bool {
cfg_if::cfg_if! {
if #[cfg(all(target_pointer_width = "64", target_vendor="apple"))] {
bytes.starts_with(Self::MAGIC_HEADER_MH_CIGAM_64)
}
else if #[cfg(all(target_pointer_width = "64", target_os="linux"))] {
bytes.starts_with(Self::MAGIC_HEADER_ELF_64)
}
else if #[cfg(all(target_pointer_width = "32", target_os="linux"))] {
bytes.starts_with(Self::MAGIC_HEADER_ELF_32)
}
else if #[cfg(all(target_pointer_width = "64", target_os="windows"))] {
bytes.starts_with(Self::MAGIC_HEADER_COFF_64)
}
else {
false
}
}
}
/// Generate a compilation
#[cfg(feature = "compiler")]
#[allow(clippy::type_complexity)]
fn generate_metadata<'data>(
data: &'data [u8],
features: &Features,
compiler: &dyn Compiler,
tunables: &dyn Tunables,
) -> Result<
(
CompileModuleInfo,
PrimaryMap<LocalFunctionIndex, FunctionBodyData<'data>>,
Vec<DataInitializer<'data>>,
Option<ModuleTranslationState>,
),
CompileError,
> {
let environ = ModuleEnvironment::new();
let translation = environ.translate(data).map_err(CompileError::Wasm)?;
// We try to apply the middleware first
let mut module = translation.module;
let middlewares = compiler.get_middlewares();
middlewares.apply_on_module_info(&mut module);
let memory_styles: PrimaryMap<MemoryIndex, MemoryStyle> = module
.memories
.values()
.map(|memory_type| tunables.memory_style(memory_type))
.collect();
let table_styles: PrimaryMap<TableIndex, TableStyle> = module
.tables
.values()
.map(|table_type| tunables.table_style(table_type))
.collect();
let compile_info = CompileModuleInfo {
module: Arc::new(module),
features: features.clone(),
memory_styles,
table_styles,
};
Ok((
compile_info,
translation.function_body_inputs,
translation.data_initializers,
translation.module_translation_state,
))
}
/// Compile a data buffer into a `DylibArtifact`, which may
/// then be instantiated.
#[cfg(feature = "compiler")]
pub fn new(
engine: &DylibEngine,
data: &[u8],
tunables: &dyn Tunables,
) -> Result<Self, CompileError> {
let mut engine_inner = engine.inner_mut();
let target = engine.target();
let compiler = engine_inner.compiler()?;
let (compile_info, function_body_inputs, data_initializers, module_translation) =
Self::generate_metadata(data, engine_inner.features(), compiler, tunables)?;
let data_initializers = data_initializers
.iter()
.map(OwnedDataInitializer::new)
.collect::<Vec<_>>()
.into_boxed_slice();
let target_triple = target.triple();
/*
// We construct the function body lengths
let function_body_lengths = compilation
.get_function_bodies()
.values()
.map(|function_body| function_body.body.len() as u64)
.map(|_function_body| 0u64)
.collect::<PrimaryMap<LocalFunctionIndex, u64>>();
*/
// TODO: we currently supply all-zero function body lengths.
// We don't know the lengths until they're compiled, yet we have to
// supply the metadata as an input to the compile.
let function_body_lengths = function_body_inputs
.keys()
.map(|_function_body| 0u64)
.collect::<PrimaryMap<LocalFunctionIndex, u64>>();
let function_frame_info = None;
let mut metadata = ModuleMetadata {
compile_info,
function_frame_info,
prefix: engine_inner.get_prefix(data),
data_initializers,
function_body_lengths,
cpu_features: target.cpu_features().as_u64(),
};
let serialized_data = metadata.serialize()?;
let mut metadata_binary = vec![];
metadata_binary.extend(MetadataHeader::new(serialized_data.len()).into_bytes());
metadata_binary.extend(serialized_data);
let (compile_info, symbol_registry) = metadata.split();
let maybe_obj_bytes = compiler.experimental_native_compile_module(
target,
compile_info,
module_translation.as_ref().unwrap(),
&function_body_inputs,
&symbol_registry,
&metadata_binary,
);
let mut extra_filepath = None;
let filepath = match maybe_obj_bytes {
Some(obj_bytes) => {
extra_filepath = {
// Create a separate object file with the trampolines.
let mut obj = get_object_for_target(target_triple).map_err(to_compile_error)?;
emit_trampolines(&mut obj, engine.target());
if obj.format() == BinaryFormat::Coff {
obj.add_coff_exports(CoffExportStyle::Gnu);
}
let file = tempfile::Builder::new()
.prefix("wasmer_dylib_")
.suffix(".o")
.tempfile()
.map_err(to_compile_error)?;
// Re-open it.
let (mut file, filepath) = file.keep().map_err(to_compile_error)?;
let obj_bytes = obj.write().map_err(to_compile_error)?;
file.write_all(&obj_bytes).map_err(to_compile_error)?;
Some(filepath)
};
// Write the object file generated by the compiler.
let obj_bytes = obj_bytes?;
let file = tempfile::Builder::new()
.prefix("wasmer_dylib_")
.suffix(".o")
.tempfile()
.map_err(to_compile_error)?;
// Re-open it.
let (mut file, filepath) = file.keep().map_err(to_compile_error)?;
file.write_all(&obj_bytes).map_err(to_compile_error)?;
filepath
}
None => {
let compilation = compiler.compile_module(
target,
compile_info,
module_translation.as_ref().unwrap(),
function_body_inputs,
)?;
let mut obj = get_object_for_target(target_triple).map_err(to_compile_error)?;
emit_trampolines(&mut obj, engine.target());
emit_data(
&mut obj,
WASMER_METADATA_SYMBOL,
&metadata_binary,
MetadataHeader::ALIGN as u64,
)
.map_err(to_compile_error)?;
let frame_info = compilation.get_frame_info();
emit_compilation(&mut obj, compilation, &symbol_registry, target_triple)
.map_err(to_compile_error)?;
if obj.format() == BinaryFormat::Coff {
obj.add_coff_exports(CoffExportStyle::Gnu);
}
let file = tempfile::Builder::new()
.prefix("wasmer_dylib_")
.suffix(".o")
.tempfile()
.map_err(to_compile_error)?;
metadata.function_frame_info = Some(frame_info);
// Re-open it.
let (mut file, filepath) = file.keep().map_err(to_compile_error)?;
let obj_bytes = obj.write().map_err(to_compile_error)?;
file.write_all(&obj_bytes).map_err(to_compile_error)?;
filepath
}
};
let output_filepath = {
let suffix = format!(".{}", Self::get_default_extension(target_triple));
let shared_file = tempfile::Builder::new()
.prefix("wasmer_dylib_")
.suffix(&suffix)
.tempfile()
.map_err(to_compile_error)?;
shared_file
.into_temp_path()
.keep()
.map_err(to_compile_error)?
};
let is_cross_compiling = engine_inner.is_cross_compiling();
let target_triple_str = {
let into_str = target_triple.to_string();
// We have to adapt the target triple string, because otherwise
// Apple's clang will not recognize it.
if into_str == "aarch64-apple-darwin" {
"arm64-apple-darwin".to_string()
} else {
into_str
}
};
// Set 'isysroot' clang flag if compiling to iOS target
let ios_compile_target = target_triple.operating_system == OperatingSystem::Ios;
let ios_sdk_flag = {
if ios_compile_target {
if target_triple.architecture == Architecture::X86_64 {
"-isysroot/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk"
} else {
"-isysroot/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk"
}
} else {
""
}
};
let ios_sdk_lib = {
if ios_compile_target {
"-lSystem"
} else {
""
}
};
// Get the location of the 'ld' linker for clang
let fuse_linker = {
let ld_install = which::which("ld");
match (ios_compile_target, ld_install) {
(true, Ok(ld_install)) => ld_install.into_os_string().into_string().unwrap(),
_ => "lld".to_string(),
}
};
let cross_compiling_args: Vec<String> = if is_cross_compiling {
vec![
format!("--target={}", target_triple_str),
format!("-fuse-ld={}", fuse_linker),
"-nodefaultlibs".to_string(),
"-nostdlib".to_string(),
ios_sdk_flag.to_string(),
ios_sdk_lib.to_string(),
]
} else {
// We are explicit on the target when the host system is
// Apple Silicon, otherwise compilation fails.
if target_triple_str == "arm64-apple-darwin" {
vec![format!("--target={}", target_triple_str)]
} else {
vec![]
}
};
let target_args = match (target_triple.operating_system, is_cross_compiling) {
(OperatingSystem::Windows, true) => vec!["-Wl,/force:unresolved,/noentry"],
(OperatingSystem::Windows, false) => vec!["-Wl,-undefined,dynamic_lookup"],
_ => vec!["-nostartfiles", "-Wl,-undefined,dynamic_lookup"],
};
trace!(
"Compiling for target {} from host {}",
target_triple_str,
Triple::host().to_string(),
);
let linker = engine_inner.linker().executable();
let output = Command::new(linker)
.arg(&filepath)
.args(&extra_filepath)
.arg("-o")
.arg(&output_filepath)
.args(&target_args)
// .args(&wasmer_symbols)
.arg("-shared")
.args(&cross_compiling_args)
.arg("-v")
.output()
.map_err(to_compile_error);
if fs::metadata(&filepath).is_ok() {
fs::remove_file(filepath).map_err(to_compile_error)?;
}
if let Some(filepath) = extra_filepath {
if fs::metadata(&filepath).is_ok() {
fs::remove_file(filepath).map_err(to_compile_error)?;
}
}
let output = output?;
if !output.status.success() {
return Err(CompileError::Codegen(format!(
"Shared object file generator failed with:\nstderr:{}\nstdout:{}",
String::from_utf8_lossy(&output.stderr).trim_end(),
String::from_utf8_lossy(&output.stdout).trim_end()
)));
}
trace!("gcc command result {:?}", output);
let mut artifact = if is_cross_compiling {
Self::from_parts_crosscompiled(metadata, output_filepath)
} else {
let lib = unsafe { Library::new(&output_filepath).map_err(to_compile_error)? };
Self::from_parts(&mut engine_inner, metadata, output_filepath, lib)
}?;
artifact.is_temporary = true;
Ok(artifact)
}
/// Get the default extension when serializing this artifact
pub fn get_default_extension(triple: &Triple) -> &'static str {
match triple.operating_system {
OperatingSystem::Windows => "dll",
OperatingSystem::Darwin | OperatingSystem::Ios | OperatingSystem::MacOSX { .. } => {
"dylib"
}
_ => "so",
}
}
/// Construct a `DylibArtifact` from component parts.
pub fn from_parts_crosscompiled(
metadata: ModuleMetadata,
dylib_path: PathBuf,
) -> Result<Self, CompileError> {
let finished_functions: PrimaryMap<LocalFunctionIndex, FunctionBodyPtr> = PrimaryMap::new();
let finished_function_call_trampolines: PrimaryMap<SignatureIndex, VMTrampoline> =
PrimaryMap::new();
let finished_dynamic_function_trampolines: PrimaryMap<FunctionIndex, FunctionBodyPtr> =
PrimaryMap::new();
let signatures: PrimaryMap<SignatureIndex, VMSharedSignatureIndex> = PrimaryMap::new();
Ok(Self {
dylib_path,
is_temporary: false,
metadata,
finished_functions: finished_functions.into_boxed_slice(),
finished_function_call_trampolines: finished_function_call_trampolines
.into_boxed_slice(),
finished_dynamic_function_trampolines: finished_dynamic_function_trampolines
.into_boxed_slice(),
func_data_registry: Arc::new(FuncDataRegistry::new()),
signatures: signatures.into_boxed_slice(),
frame_info_registration: Mutex::new(None),
})
}
/// Construct a `DylibArtifact` from component parts.
pub fn from_parts(
engine_inner: &mut DylibEngineInner,
metadata: ModuleMetadata,
dylib_path: PathBuf,
lib: Library,
) -> Result<Self, CompileError> {
unsafe {
let trampolines_symbol: LibrarySymbol<usize> = lib
.get(WASMER_TRAMPOLINES_SYMBOL)
.expect("missing WASMER_TRAMPOLINES symbol");
fill_trampoline_table(trampolines_symbol.into_raw().into_raw() as *mut usize);
}
let mut finished_functions: PrimaryMap<LocalFunctionIndex, FunctionBodyPtr> =
PrimaryMap::new();
for (function_local_index, _function_len) in metadata.function_body_lengths.iter() {
let function_name = metadata
.get_symbol_registry()
.symbol_to_name(Symbol::LocalFunction(function_local_index));
unsafe {
// We use a fake function signature `fn()` because we just
// want to get the function address.
let func: LibrarySymbol<unsafe extern "C" fn()> = lib
.get(function_name.as_bytes())
.map_err(to_compile_error)?;
finished_functions.push(FunctionBodyPtr(
func.into_raw().into_raw() as *const VMFunctionBody
));
}
}
// Retrieve function call trampolines
let mut finished_function_call_trampolines: PrimaryMap<SignatureIndex, VMTrampoline> =
PrimaryMap::with_capacity(metadata.compile_info.module.signatures.len());
for sig_index in metadata.compile_info.module.signatures.keys() {
let function_name = metadata
.get_symbol_registry()
.symbol_to_name(Symbol::FunctionCallTrampoline(sig_index));
unsafe {
let trampoline: LibrarySymbol<VMTrampoline> = lib
.get(function_name.as_bytes())
.map_err(to_compile_error)?;
let raw = *trampoline.into_raw();
finished_function_call_trampolines.push(raw);
}
}
// Retrieve dynamic function trampolines (only for imported functions)
let mut finished_dynamic_function_trampolines: PrimaryMap<FunctionIndex, FunctionBodyPtr> =
PrimaryMap::with_capacity(metadata.compile_info.module.num_imported_functions);
for func_index in metadata
.compile_info
.module
.functions
.keys()
.take(metadata.compile_info.module.num_imported_functions)
{
let function_name = metadata
.get_symbol_registry()
.symbol_to_name(Symbol::DynamicFunctionTrampoline(func_index));
unsafe {
let trampoline: LibrarySymbol<unsafe extern "C" fn()> = lib
.get(function_name.as_bytes())
.map_err(to_compile_error)?;
finished_dynamic_function_trampolines.push(FunctionBodyPtr(
trampoline.into_raw().into_raw() as *const VMFunctionBody,
));
}
}
// Compute indices into the shared signature table.
let signatures = {
metadata
.compile_info
.module
.signatures
.values()
.map(|sig| engine_inner.signatures().register(sig))
.collect::<PrimaryMap<_, _>>()
};
engine_inner.add_library(lib);
Ok(Self {
dylib_path,
is_temporary: false,
metadata,
finished_functions: finished_functions.into_boxed_slice(),
finished_function_call_trampolines: finished_function_call_trampolines
.into_boxed_slice(),
finished_dynamic_function_trampolines: finished_dynamic_function_trampolines
.into_boxed_slice(),
func_data_registry: engine_inner.func_data().clone(),
signatures: signatures.into_boxed_slice(),
frame_info_registration: Mutex::new(None),
})
}
/// Compile a data buffer into a `DylibArtifact`, which may
/// then be instantiated.
#[cfg(not(feature = "compiler"))]
pub fn new(_engine: &DylibEngine, _data: &[u8]) -> Result<Self, CompileError> {
Err(CompileError::Codegen(
"Compilation is not enabled in the engine".to_string(),
))
}
/// Deserialize a `DylibArtifact` from bytes.
///
/// # Safety
///
/// The bytes must represent a serialized WebAssembly module.
pub unsafe fn deserialize(
engine: &DylibEngine,
bytes: &[u8],
) -> Result<Self, DeserializeError> {
if !Self::is_deserializable(bytes) {
return Err(DeserializeError::Incompatible(
"The provided bytes are not in any native format Wasmer can understand".to_string(),
));
}
// Dump the bytes into a file, so we can read it with our `dlopen`
let named_file = NamedTempFile::new()?;
let (mut file, path) = named_file.keep().map_err(|e| e.error)?;
file.write_all(bytes)?;
// We already checked for the header, so we don't need
// to check again.
let mut artifact = Self::deserialize_from_file_unchecked(engine, &path)?;
artifact.is_temporary = true;
Ok(artifact)
}
/// Deserialize a `DylibArtifact` from a file path.
///
/// # Safety
///
/// The file's content must represent a serialized WebAssembly module.
pub unsafe fn deserialize_from_file(
engine: &DylibEngine,
path: &Path,
) -> Result<Self, DeserializeError> {
let mut file = File::open(&path)?;
let mut buffer = [0; 5];
// read up to 5 bytes
file.read_exact(&mut buffer)?;
if !Self::is_deserializable(&buffer) {
return Err(DeserializeError::Incompatible(
"The provided bytes are not in any native format Wasmer can understand".to_string(),
));
}
Self::deserialize_from_file_unchecked(engine, path)
}
/// Deserialize a `DylibArtifact` from a file path (unchecked).
///
/// # Safety
///
/// The file's content must represent a serialized WebAssembly module.
pub unsafe fn deserialize_from_file_unchecked(
engine: &DylibEngine,
path: &Path,
) -> Result<Self, DeserializeError> {
let lib = Library::new(&path).map_err(|e| {
DeserializeError::CorruptedBinary(format!("Library loading failed: {}", e))
})?;
let shared_path: PathBuf = PathBuf::from(path);
let metadata_symbol: LibrarySymbol<*mut [u8; MetadataHeader::LEN]> =
lib.get(WASMER_METADATA_SYMBOL).map_err(|e| {
DeserializeError::CorruptedBinary(format!(
"The provided object file doesn't seem to be generated by Wasmer: {}",
e
))
})?;
use std::slice;
let metadata = &**metadata_symbol;
let metadata_len = MetadataHeader::parse(metadata)?;
let metadata_slice: &'static [u8] =
slice::from_raw_parts(metadata.as_ptr().add(MetadataHeader::LEN), metadata_len);
let metadata = ModuleMetadata::deserialize(metadata_slice)?;
let mut engine_inner = engine.inner_mut();
Self::from_parts(&mut engine_inner, metadata, shared_path, lib)
.map_err(DeserializeError::Compiler)
}
/// Used in test deserialize metadata is correct
pub fn metadata(&self) -> &ModuleMetadata {
&self.metadata
}
}
impl ArtifactCreate for DylibArtifact {
fn module(&self) -> Arc<ModuleInfo> {
self.metadata.compile_info.module.clone()
}
fn module_ref(&self) -> &ModuleInfo {
&self.metadata.compile_info.module
}
fn module_mut(&mut self) -> Option<&mut ModuleInfo> {
Arc::get_mut(&mut self.metadata.compile_info.module)
}
fn features(&self) -> &Features {
&self.metadata.compile_info.features
}
fn cpu_features(&self) -> enumset::EnumSet<CpuFeature> {
EnumSet::from_u64(self.metadata.cpu_features)
}
fn data_initializers(&self) -> &[OwnedDataInitializer] {
&*self.metadata.data_initializers
}
fn memory_styles(&self) -> &PrimaryMap<MemoryIndex, MemoryStyle> {
&self.metadata.compile_info.memory_styles
}
fn table_styles(&self) -> &PrimaryMap<TableIndex, TableStyle> {
&self.metadata.compile_info.table_styles
}
/// Serialize a `DylibArtifact`.
fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
Ok(std::fs::read(&self.dylib_path)?)
}
/// Serialize a `DylibArtifact` to a portable file
#[cfg(feature = "compiler")]
fn serialize_to_file(&self, path: &Path) -> Result<(), SerializeError> {
let serialized = self.serialize()?;
std::fs::write(&path, serialized)?;
/*
When you write the artifact to a new file it still has the 'Mach-O Identifier'
of the original file, and so this can causes linker issues when adding
the new file to an XCode project.
The below code renames the ID of the file so that it references itself through
an @executable_path prefix. Basically it tells XCode to find this file
inside of the projects' list of 'linked executables'.
You need to be running MacOS for the following to actually work though.
*/
let has_extension = path.extension().is_some();
if has_extension && path.extension().unwrap() == "dylib" {
let filename = path.file_name().unwrap().to_str().unwrap();
let parent_dir = path.parent().unwrap();
let absolute_path = std::fs::canonicalize(&parent_dir)
.unwrap()
.into_os_string()
.into_string()
.unwrap();
Command::new("install_name_tool")
.arg("-id")
.arg(format!("@executable_path/{}", &filename))
.arg(&filename)
.current_dir(&absolute_path)
.output()?;
}
Ok(())
}
}
impl Artifact for DylibArtifact {
fn register_frame_info(&self) {
let mut info = self.frame_info_registration.lock().unwrap();
if info.is_some() {
return;
}
// We (reverse) order all the functions by their pointer location.
// [f9, f6, f7, f8...] and calculate their potential function body size by
// getting the diff in pointers between functions (since they are all located
// in the same __text section).
let min_call_trampolines_pointer = self
.finished_function_call_trampolines
.values()
.map(|t| *t as usize)
.min()
.unwrap_or(0);
let min_dynamic_trampolines_pointer = self
.finished_dynamic_function_trampolines
.values()
.map(|t| **t as usize)
.min()
.unwrap_or(0);
let fp = self.finished_functions.clone();
let mut function_pointers = fp.into_iter().collect::<Vec<_>>();
// Sort the keys by the funciton pointer values in reverse order.
// This way we can get the maximum function lengths (since functions can't overlap in memory)
function_pointers.sort_by(|(_k1, v1), (_k2, v2)| v2.cmp(v1));
let mut iter = function_pointers.into_iter();
let mut function_pointers = iter
.next()
.map(|(index, function_pointer)| {
let fp = **function_pointer as usize;
// In case we are in the first function pointer (the one with the highest pointer)
// we try to determine it's bounds (function size) by using the other function trampoline
// locations.
let current_size_by_ptr = if fp < min_call_trampolines_pointer {
if min_call_trampolines_pointer < min_dynamic_trampolines_pointer
|| min_dynamic_trampolines_pointer == 0
{
min_call_trampolines_pointer - fp
} else {
min_dynamic_trampolines_pointer - fp
}
} else if fp < min_dynamic_trampolines_pointer {
min_dynamic_trampolines_pointer - fp
} else {
// The trampoline pointers are before the function.
// We can safely assume the function will be at least 16 bits of length.
// This is a very hacky assumption, but it makes collisions work perfectly
// Since DLOpen simlinks will always be > 16 bits of difference between
// two different libraries for the same symbol.
// Note: the minmum Mach-O file is 0x1000 bytes and the minimum ELF is 0x0060 bytes
16
};
let mut prev_pointer = fp;
// We choose the minimum between the function size given the pointer diff
// and the emitted size by the address map
let ptr = function_pointer;
let length = current_size_by_ptr;
let first = (index, FunctionExtent { ptr: *ptr, length });
std::iter::once(first)
.chain(iter.map(|(index, function_pointer)| {
let fp = **function_pointer as usize;
// This assumes we never lay any functions bodies across the usize::MAX..nullptr
// wrapping point.
// Which is generally true on most OSes, but certainly doesn't have to be true.
//
// Further reading: https://lwn.net/Articles/342330/ \
// "There is one little problem with that reasoning, though: NULL (zero) can
// actually be a valid pointer address."
let current_size_by_ptr = prev_pointer - fp;
prev_pointer = fp;
// We choose the minimum between the function size given the pointer diff
// and the emitted size by the address map
let ptr = function_pointer;
let length = current_size_by_ptr;
(index, FunctionExtent { ptr: *ptr, length })
}))
.collect::<Vec<_>>()
})
.unwrap_or_default();
// We sort them again, by key this time
function_pointers.sort_by(|(k1, _v1), (k2, _v2)| k1.cmp(k2));
let frame_infos = if self.metadata().function_frame_info.is_some() {
self.metadata().function_frame_info.clone().unwrap()
} else {
function_pointers
.iter()
.map(|(_, extent)| CompiledFunctionFrameInfo {
traps: vec![],
address_map: FunctionAddressMap {
body_len: extent.length,
..Default::default()
},
})
.collect::<PrimaryMap<LocalFunctionIndex, _>>()
};
let finished_function_extents = function_pointers
.into_iter()
.map(|(_, function_extent)| function_extent)
.collect::<PrimaryMap<LocalFunctionIndex, _>>()
.into_boxed_slice();
*info = register_frame_info(
self.metadata.compile_info.module.clone(),
&finished_function_extents,
frame_infos,
);
}
fn finished_functions(&self) -> &BoxedSlice<LocalFunctionIndex, FunctionBodyPtr> {
&self.finished_functions
}
fn finished_function_call_trampolines(&self) -> &BoxedSlice<SignatureIndex, VMTrampoline> {
&self.finished_function_call_trampolines
}
fn finished_dynamic_function_trampolines(&self) -> &BoxedSlice<FunctionIndex, FunctionBodyPtr> {
&self.finished_dynamic_function_trampolines
}
fn signatures(&self) -> &BoxedSlice<SignatureIndex, VMSharedSignatureIndex> {
&self.signatures
}
fn func_data_registry(&self) -> &FuncDataRegistry {
&self.func_data_registry
}
fn preinstantiate(&self) -> Result<(), InstantiationError> {
Ok(())
}
}

View File

@ -1,117 +0,0 @@
use crate::DylibEngine;
use wasmer_compiler::{CompilerConfig, Features, Target};
/// The Dylib builder
pub struct Dylib {
compiler_config: Option<Box<dyn CompilerConfig>>,
target: Option<Target>,
features: Option<Features>,
}
impl Dylib {
#[cfg(feature = "compiler")]
/// Create a new Dylib builder.
pub fn new<T>(compiler_config: T) -> Self
where
T: Into<Box<dyn CompilerConfig>>,
{
let mut compiler_config = compiler_config.into();
compiler_config.enable_pic();
Self {
compiler_config: Some(compiler_config),
target: None,
features: None,
}
}
/// Create a new headless Dylib builder.
pub fn headless() -> Self {
Self {
compiler_config: None,
target: None,
features: None,
}
}
/// Set the target
pub fn target(mut self, target: Target) -> Self {
self.target = Some(target);
self
}
/// Set the features
pub fn features(mut self, features: Features) -> Self {
self.features = Some(features);
self
}
/// Build the `DylibEngine` for this configuration
pub fn engine(self) -> DylibEngine {
if let Some(_compiler_config) = self.compiler_config {
#[cfg(feature = "compiler")]
{
let compiler_config = _compiler_config;
let target = self.target.unwrap_or_default();
let features = self
.features
.unwrap_or_else(|| compiler_config.default_features_for_target(&target));
let compiler = compiler_config.compiler();
DylibEngine::new(compiler, target, features)
}
#[cfg(not(feature = "compiler"))]
{
unreachable!("Cannot call `DylibEngine::new` without the `compiler` feature")
}
} else {
DylibEngine::headless()
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[cfg(feature = "compiler")]
use std::sync::Arc;
#[cfg(feature = "compiler")]
use wasmer_compiler::{Compiler, ModuleMiddleware};
#[cfg(feature = "compiler")]
#[derive(Default)]
pub struct TestCompilerConfig {
pub enabled_pic: bool,
pub middlewares: Vec<Arc<dyn ModuleMiddleware>>,
}
#[cfg(feature = "compiler")]
impl CompilerConfig for TestCompilerConfig {
fn enable_pic(&mut self) {
self.enabled_pic = true;
}
fn compiler(self: Box<Self>) -> Box<dyn Compiler> {
unimplemented!("compiler not implemented");
}
fn push_middleware(&mut self, middleware: Arc<dyn ModuleMiddleware>) {
self.middlewares.push(middleware);
}
}
#[cfg(feature = "compiler")]
#[test]
#[should_panic(expected = "compiler not implemented")]
fn build_engine() {
let compiler_config = TestCompilerConfig::default();
let dylib = Dylib::new(compiler_config);
let _engine = dylib.engine();
}
#[test]
fn build_headless_engine() {
let dylib = Dylib::headless();
let _engine = dylib.engine();
}
}

View File

@ -1,325 +0,0 @@
//! Dylib Engine.
use crate::DylibArtifact;
use libloading::Library;
use std::path::Path;
use std::sync::Arc;
use std::sync::Mutex;
use wasmer_compiler::{CompileError, Target};
#[cfg(feature = "compiler")]
use wasmer_compiler::{Compiler, Triple};
use wasmer_engine::{Artifact, DeserializeError, Engine, EngineId, Tunables};
#[cfg(feature = "compiler")]
use wasmer_types::Features;
use wasmer_types::FunctionType;
use wasmer_vm::{
FuncDataRegistry, SignatureRegistry, VMCallerCheckedAnyfunc, VMFuncRef, VMSharedSignatureIndex,
};
/// A WebAssembly `Dylib` Engine.
#[derive(Clone)]
pub struct DylibEngine {
inner: Arc<Mutex<DylibEngineInner>>,
/// The target for the compiler
target: Arc<Target>,
engine_id: EngineId,
}
impl DylibEngine {
/// Create a new `DylibEngine` with the given config
#[cfg(feature = "compiler")]
pub fn new(compiler: Box<dyn Compiler>, target: Target, features: Features) -> Self {
let is_cross_compiling = *target.triple() != Triple::host();
let linker = Linker::find_linker(is_cross_compiling);
Self {
inner: Arc::new(Mutex::new(DylibEngineInner {
compiler: Some(compiler),
signatures: SignatureRegistry::new(),
func_data: Arc::new(FuncDataRegistry::new()),
prefixer: None,
features,
is_cross_compiling,
linker,
libraries: vec![],
})),
target: Arc::new(target),
engine_id: EngineId::default(),
}
}
/// Create a headless `DylibEngine`
///
/// A headless engine is an engine without any compiler attached.
/// This is useful for assuring a minimal runtime for running
/// WebAssembly modules.
///
/// For example, for running in IoT devices where compilers are very
/// expensive, or also to optimize startup speed.
///
/// # Important
///
/// Headless engines can't compile or validate any modules,
/// they just take already processed Modules (via `Module::serialize`).
pub fn headless() -> Self {
Self {
inner: Arc::new(Mutex::new(DylibEngineInner {
#[cfg(feature = "compiler")]
compiler: None,
#[cfg(feature = "compiler")]
features: Features::default(),
signatures: SignatureRegistry::new(),
func_data: Arc::new(FuncDataRegistry::new()),
prefixer: None,
is_cross_compiling: false,
linker: Linker::None,
libraries: vec![],
})),
target: Arc::new(Target::default()),
engine_id: EngineId::default(),
}
}
/// Sets a prefixer for the wasm module, so we can avoid any collisions
/// in the exported function names on the generated shared object.
///
/// This, allows us to rather than have functions named `wasmer_function_1`
/// to be named `wasmer_function_PREFIX_1`.
///
/// # Important
///
/// This prefixer function should be deterministic, so the compilation
/// remains deterministic.
pub fn set_deterministic_prefixer<F>(&mut self, prefixer: F)
where
F: Fn(&[u8]) -> String + Send + 'static,
{
let mut inner = self.inner_mut();
inner.prefixer = Some(Box::new(prefixer));
}
pub(crate) fn inner(&self) -> std::sync::MutexGuard<'_, DylibEngineInner> {
self.inner.lock().unwrap()
}
pub(crate) fn inner_mut(&self) -> std::sync::MutexGuard<'_, DylibEngineInner> {
self.inner.lock().unwrap()
}
}
impl Engine for DylibEngine {
/// The target
fn target(&self) -> &Target {
&self.target
}
/// Register a signature
fn register_signature(&self, func_type: &FunctionType) -> VMSharedSignatureIndex {
let compiler = self.inner();
compiler.signatures().register(func_type)
}
fn register_function_metadata(&self, func_data: VMCallerCheckedAnyfunc) -> VMFuncRef {
let compiler = self.inner();
compiler.func_data().register(func_data)
}
/// Lookup a signature
fn lookup_signature(&self, sig: VMSharedSignatureIndex) -> Option<FunctionType> {
let compiler = self.inner();
compiler.signatures().lookup(sig)
}
/// Validates a WebAssembly module
fn validate(&self, binary: &[u8]) -> Result<(), CompileError> {
self.inner().validate(binary)
}
/// Compile a WebAssembly binary
#[cfg(feature = "compiler")]
fn compile(
&self,
binary: &[u8],
tunables: &dyn Tunables,
) -> Result<Arc<dyn Artifact>, CompileError> {
Ok(Arc::new(DylibArtifact::new(self, binary, tunables)?))
}
/// Compile a WebAssembly binary (it will fail because the `compiler` flag is disabled).
#[cfg(not(feature = "compiler"))]
fn compile(
&self,
_binary: &[u8],
_tunables: &dyn Tunables,
) -> Result<Arc<dyn Artifact>, CompileError> {
Err(CompileError::Codegen(
"The `DylibEngine` is operating in headless mode, so it cannot compile a module."
.to_string(),
))
}
/// Deserializes a WebAssembly module (binary content of a shared object file)
unsafe fn deserialize(&self, bytes: &[u8]) -> Result<Arc<dyn Artifact>, DeserializeError> {
Ok(Arc::new(DylibArtifact::deserialize(self, bytes)?))
}
/// Deserializes a WebAssembly module from a path
/// It should point to a shared object file generated by this engine.
unsafe fn deserialize_from_file(
&self,
file_ref: &Path,
) -> Result<Arc<dyn Artifact>, DeserializeError> {
Ok(Arc::new(DylibArtifact::deserialize_from_file(
self, file_ref,
)?))
}
fn id(&self) -> &EngineId {
&self.engine_id
}
fn cloned(&self) -> Arc<dyn Engine + Send + Sync> {
Arc::new(self.clone())
}
}
#[derive(Clone, Copy)]
pub(crate) enum Linker {
None,
Clang11,
Clang10,
Clang,
Gcc,
}
impl Linker {
#[cfg(feature = "compiler")]
fn find_linker(is_cross_compiling: bool) -> Self {
let (possibilities, requirements): (&[_], _) = if is_cross_compiling {
(
&[Self::Clang11, Self::Clang10, Self::Clang],
"at least one of `clang-11`, `clang-10`, or `clang`",
)
} else {
(&[Self::Gcc], "`gcc`")
};
*possibilities
.iter()
.find(|linker| which::which(linker.executable()).is_ok())
.unwrap_or_else(|| {
panic!(
"Need {} installed in order to use `DylibEngine` when {}cross-compiling",
requirements,
if is_cross_compiling { "" } else { "not " }
)
})
}
pub(crate) fn executable(self) -> &'static str {
match self {
Self::None => "",
Self::Clang11 => "clang-11",
Self::Clang10 => "clang-10",
Self::Clang => "clang",
Self::Gcc => "gcc",
}
}
}
/// The inner contents of `DylibEngine`
pub struct DylibEngineInner {
/// The compiler
#[cfg(feature = "compiler")]
compiler: Option<Box<dyn Compiler>>,
/// The WebAssembly features to use
#[cfg(feature = "compiler")]
features: Features,
/// The signature registry is used mainly to operate with trampolines
/// performantly.
signatures: SignatureRegistry,
/// The backing storage of `VMFuncRef`s. This centralized store ensures that 2
/// functions with the same `VMCallerCheckedAnyfunc` will have the same `VMFuncRef`.
/// It also guarantees that the `VMFuncRef`s stay valid until the engine is dropped.
func_data: Arc<FuncDataRegistry>,
/// The prefixer returns the a String to prefix each of
/// the functions in the shared object generated by the `DylibEngine`,
/// so we can assure no collisions.
prefixer: Option<Box<dyn Fn(&[u8]) -> String + Send>>,
/// Whether the Dylib engine will cross-compile.
is_cross_compiling: bool,
/// The linker to use.
linker: Linker,
/// List of libraries loaded by this engine.
libraries: Vec<Library>,
}
impl DylibEngineInner {
/// Gets the compiler associated to this engine.
#[cfg(feature = "compiler")]
pub fn compiler(&self) -> Result<&dyn Compiler, CompileError> {
if self.compiler.is_none() {
return Err(CompileError::Codegen("The `DylibEngine` is operating in headless mode, so it can only execute already compiled Modules.".to_string()));
}
Ok(&**self
.compiler
.as_ref()
.expect("Can't get compiler reference"))
}
#[cfg(feature = "compiler")]
pub(crate) fn get_prefix(&self, bytes: &[u8]) -> String {
if let Some(prefixer) = &self.prefixer {
prefixer(bytes)
} else {
"".to_string()
}
}
#[cfg(feature = "compiler")]
pub(crate) fn features(&self) -> &Features {
&self.features
}
/// Validate the module
#[cfg(feature = "compiler")]
pub fn validate(&self, data: &[u8]) -> Result<(), CompileError> {
self.compiler()?.validate_module(self.features(), data)
}
/// Validate the module
#[cfg(not(feature = "compiler"))]
pub fn validate<'data>(&self, _data: &'data [u8]) -> Result<(), CompileError> {
Err(CompileError::Validate(
"The `DylibEngine` is not compiled with compiler support, which is required for validating".to_string(),
))
}
/// Shared signature registry.
pub fn signatures(&self) -> &SignatureRegistry {
&self.signatures
}
/// Shared func metadata registry.
pub(crate) fn func_data(&self) -> &Arc<FuncDataRegistry> {
&self.func_data
}
pub(crate) fn is_cross_compiling(&self) -> bool {
self.is_cross_compiling
}
pub(crate) fn linker(&self) -> Linker {
self.linker
}
pub(crate) fn add_library(&mut self, library: Library) {
self.libraries.push(library);
}
}

View File

@ -1,36 +0,0 @@
//! Dylib Engine for Wasmer compilers.
//!
//! Given a compiler (such as `CraneliftCompiler` or `LLVMCompiler`)
//! it generates a dylib/shared object file (`.so` or `.dylib`
//! depending on the target), saves it temporarily to disk and uses it
//! natively via `dlopen` and `dlsym` (using the `libloading`
//! library).
#![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)]
#![warn(unused_import_braces)]
#![cfg_attr(feature = "cargo-clippy", allow(clippy::new_without_default))]
#![cfg_attr(
feature = "cargo-clippy",
warn(
clippy::float_arithmetic,
clippy::mut_mut,
clippy::nonminimal_bool,
clippy::map_unwrap_or,
clippy::print_stdout,
clippy::unicode_not_nfc,
clippy::use_self
)
)]
mod artifact;
mod builder;
mod engine;
mod serialize;
mod trampoline;
pub use crate::artifact::DylibArtifact;
pub use crate::builder::Dylib;
pub use crate::engine::DylibEngine;
/// Version number of this crate.
pub const VERSION: &str = env!("CARGO_PKG_VERSION");

View File

@ -1,139 +0,0 @@
use rkyv::{
archived_value, de::deserializers::SharedDeserializeMap, ser::serializers::AllocSerializer,
ser::Serializer as RkyvSerializer, Archive, Deserialize as RkyvDeserialize,
Serialize as RkyvSerialize,
};
use serde::{Deserialize, Serialize};
use std::error::Error;
use wasmer_compiler::{
CompileError, CompileModuleInfo, CompiledFunctionFrameInfo, SectionIndex, Symbol,
SymbolRegistry,
};
use wasmer_engine::DeserializeError;
use wasmer_types::entity::{EntityRef, PrimaryMap};
use wasmer_types::{FunctionIndex, LocalFunctionIndex, OwnedDataInitializer, SignatureIndex};
fn to_compile_error(err: impl Error) -> CompileError {
CompileError::Codegen(format!("{}", err))
}
/// Serializable struct that represents the compiled metadata.
#[derive(Serialize, Deserialize, Debug, RkyvSerialize, RkyvDeserialize, Archive, PartialEq, Eq)]
pub struct ModuleMetadata {
pub compile_info: CompileModuleInfo,
pub function_frame_info: Option<PrimaryMap<LocalFunctionIndex, CompiledFunctionFrameInfo>>,
pub prefix: String,
pub data_initializers: Box<[OwnedDataInitializer]>,
// The function body lengths (used to find function by address)
pub function_body_lengths: PrimaryMap<LocalFunctionIndex, u64>,
pub cpu_features: u64,
}
pub struct ModuleMetadataSymbolRegistry<'a> {
pub prefix: &'a String,
}
impl ModuleMetadata {
pub fn split(&'_ mut self) -> (&'_ mut CompileModuleInfo, ModuleMetadataSymbolRegistry<'_>) {
let compile_info = &mut self.compile_info;
let symbol_registry = ModuleMetadataSymbolRegistry {
prefix: &self.prefix,
};
(compile_info, symbol_registry)
}
pub fn get_symbol_registry(&'_ self) -> ModuleMetadataSymbolRegistry<'_> {
ModuleMetadataSymbolRegistry {
prefix: &self.prefix,
}
}
pub fn serialize(&mut self) -> Result<Vec<u8>, CompileError> {
let mut serializer = AllocSerializer::<4096>::default();
let pos = serializer.serialize_value(self).map_err(to_compile_error)? as u64;
let mut serialized_data = serializer.into_serializer().into_inner();
serialized_data.extend_from_slice(&pos.to_le_bytes());
Ok(serialized_data.to_vec())
}
pub unsafe fn deserialize(metadata_slice: &[u8]) -> Result<Self, DeserializeError> {
let archived = Self::archive_from_slice(metadata_slice)?;
Self::deserialize_from_archive(archived)
}
unsafe fn archive_from_slice(
metadata_slice: &[u8],
) -> Result<&ArchivedModuleMetadata, DeserializeError> {
let mut pos: [u8; 8] = Default::default();
pos.copy_from_slice(&metadata_slice[metadata_slice.len() - 8..metadata_slice.len()]);
let pos: u64 = u64::from_le_bytes(pos);
Ok(archived_value::<Self>(
&metadata_slice[..metadata_slice.len() - 8],
pos as usize,
))
}
pub fn deserialize_from_archive(
archived: &ArchivedModuleMetadata,
) -> Result<Self, DeserializeError> {
let mut deserializer = SharedDeserializeMap::new();
RkyvDeserialize::deserialize(archived, &mut deserializer)
.map_err(|e| DeserializeError::CorruptedBinary(format!("{:?}", e)))
}
}
impl<'a> SymbolRegistry for ModuleMetadataSymbolRegistry<'a> {
fn symbol_to_name(&self, symbol: Symbol) -> String {
match symbol {
Symbol::LocalFunction(index) => {
format!("wasmer_function_{}_{}", self.prefix, index.index())
}
Symbol::Section(index) => format!("wasmer_section_{}_{}", self.prefix, index.index()),
Symbol::FunctionCallTrampoline(index) => {
format!(
"wasmer_trampoline_function_call_{}_{}",
self.prefix,
index.index()
)
}
Symbol::DynamicFunctionTrampoline(index) => {
format!(
"wasmer_trampoline_dynamic_function_{}_{}",
self.prefix,
index.index()
)
}
}
}
fn name_to_symbol(&self, name: &str) -> Option<Symbol> {
if let Some(index) = name.strip_prefix(&format!("wasmer_function_{}_", self.prefix)) {
index
.parse::<u32>()
.ok()
.map(|index| Symbol::LocalFunction(LocalFunctionIndex::from_u32(index)))
} else if let Some(index) = name.strip_prefix(&format!("wasmer_section_{}_", self.prefix)) {
index
.parse::<u32>()
.ok()
.map(|index| Symbol::Section(SectionIndex::from_u32(index)))
} else if let Some(index) =
name.strip_prefix(&format!("wasmer_trampoline_function_call_{}_", self.prefix))
{
index
.parse::<u32>()
.ok()
.map(|index| Symbol::FunctionCallTrampoline(SignatureIndex::from_u32(index)))
} else if let Some(index) = name.strip_prefix(&format!(
"wasmer_trampoline_dynamic_function_{}_",
self.prefix
)) {
index
.parse::<u32>()
.ok()
.map(|index| Symbol::DynamicFunctionTrampoline(FunctionIndex::from_u32(index)))
} else {
None
}
}
}

View File

@ -1,166 +0,0 @@
//! Trampolines for libcalls.
//!
//! This is needed because the target of libcall relocations are not reachable
//! through normal branch instructions.
//!
//! There is an additional complexity for dynamic libraries: we can't just
//! import the symbol from the host executable because executables don't export
//! dynamic symbols (it's possible but requires special linker options).
//!
//! Instead, we export a table of function pointers in the data section which is
//! manually filled in by the runtime after the dylib is loaded.
use enum_iterator::IntoEnumIterator;
use object::{
elf, macho,
write::{Object, Relocation, SectionId, StandardSection, Symbol, SymbolId, SymbolSection},
BinaryFormat, RelocationEncoding, RelocationKind, SymbolFlags, SymbolKind, SymbolScope,
};
use wasmer_compiler::{Architecture, Target};
use wasmer_vm::libcalls::{function_pointer, LibCall};
/// Symbol exported from the dynamic library which points to the trampoline table.
pub const WASMER_TRAMPOLINES_SYMBOL: &[u8] = b"WASMER_TRAMPOLINES";
// SystemV says that both x16 and x17 are available as intra-procedural scratch
// registers but Apple's ABI restricts us to use x17.
// ADRP x17, #... 11 00 00 90
// LDR x17, [x17, #...] 31 02 40 f9
// BR x17 20 02 1f d6
const AARCH64_TRAMPOLINE: [u8; 12] = [
0x11, 0x00, 0x00, 0x90, 0x31, 0x02, 0x40, 0xf9, 0x20, 0x02, 0x1f, 0xd6,
];
// JMP [RIP + ...] FF 25 00 00 00 00
const X86_64_TRAMPOLINE: [u8; 6] = [0xff, 0x25, 0x00, 0x00, 0x00, 0x00];
fn emit_trampoline(
obj: &mut Object,
text: SectionId,
trampoline_table_symbols: &[SymbolId],
libcall: LibCall,
target: &Target,
) {
let function_name = libcall.to_function_name();
let libcall_symbol = obj.add_symbol(Symbol {
name: function_name.as_bytes().to_vec(),
value: 0,
size: 0,
kind: SymbolKind::Text,
scope: SymbolScope::Linkage,
weak: false,
section: SymbolSection::Section(text),
flags: SymbolFlags::None,
});
match target.triple().architecture {
Architecture::Aarch64(_) => {
let (reloc1, reloc2) = match obj.format() {
BinaryFormat::Elf => (
RelocationKind::Elf(elf::R_AARCH64_ADR_PREL_PG_HI21),
RelocationKind::Elf(elf::R_AARCH64_LDST64_ABS_LO12_NC),
),
BinaryFormat::MachO => (
RelocationKind::MachO {
value: macho::ARM64_RELOC_PAGE21,
relative: true,
},
RelocationKind::MachO {
value: macho::ARM64_RELOC_PAGEOFF12,
relative: false,
},
),
_ => panic!("Unsupported binary format on AArch64"),
};
let offset = obj.add_symbol_data(libcall_symbol, text, &AARCH64_TRAMPOLINE, 4);
obj.add_relocation(
text,
Relocation {
offset,
size: 32,
kind: reloc1,
encoding: RelocationEncoding::Generic,
symbol: trampoline_table_symbols[libcall as usize],
addend: 0,
},
)
.unwrap();
obj.add_relocation(
text,
Relocation {
offset: offset + 4,
size: 32,
kind: reloc2,
encoding: RelocationEncoding::Generic,
symbol: trampoline_table_symbols[libcall as usize],
addend: 0,
},
)
.unwrap();
}
Architecture::X86_64 => {
let offset = obj.add_symbol_data(libcall_symbol, text, &X86_64_TRAMPOLINE, 1);
obj.add_relocation(
text,
Relocation {
offset: offset + 2,
size: 32,
kind: RelocationKind::Relative,
encoding: RelocationEncoding::Generic,
symbol: trampoline_table_symbols[libcall as usize],
// -4 because RIP-relative addressing starts from the end of
// the instruction.
addend: -4,
},
)
.unwrap();
}
arch => panic!("Unsupported architecture: {}", arch),
};
}
/// Emits the libcall trampolines and table to the object file.
pub fn emit_trampolines(obj: &mut Object, target: &Target) {
let text = obj.section_id(StandardSection::Text);
let bss = obj.section_id(StandardSection::UninitializedData);
let trampoline_table = obj.add_symbol(Symbol {
name: WASMER_TRAMPOLINES_SYMBOL.to_vec(),
value: 0,
size: 0,
kind: SymbolKind::Data,
scope: SymbolScope::Dynamic,
weak: false,
section: SymbolSection::Section(bss),
flags: SymbolFlags::None,
});
let table_offset =
obj.add_symbol_bss(trampoline_table, bss, LibCall::VARIANT_COUNT as u64 * 8, 8);
// Create a symbol for each entry in the table. We could avoid this and use
// an addend, but this isn't supported in all object formats.
let mut trampoline_table_symbols = vec![];
for libcall in LibCall::into_enum_iter() {
trampoline_table_symbols.push(obj.add_symbol(Symbol {
name: format!("__WASMER_TRAMPOLINE{}", libcall as usize).into_bytes(),
value: table_offset + libcall as u64 * 8,
size: 0,
kind: SymbolKind::Data,
scope: SymbolScope::Compilation,
weak: false,
section: SymbolSection::Section(bss),
flags: SymbolFlags::None,
}));
}
for libcall in LibCall::into_enum_iter() {
emit_trampoline(obj, text, &trampoline_table_symbols, libcall, target);
}
}
/// Fills in the libcall trampoline table at the given address.
pub unsafe fn fill_trampoline_table(table: *mut usize) {
for libcall in LibCall::into_enum_iter() {
*table.add(libcall as usize) = function_pointer(libcall);
}
}

View File

@ -5,14 +5,13 @@ This crate is the general abstraction for creating Engines in Wasmer.
Wasmer Engines are mainly responsible for two things:
* Transform the compilation code (from any Wasmer Compiler) to
**create** an `Artifact`,
* **Load** an`Artifact` so it can be used by the user (normally,
* **Load** an `Artifact` so it can be used by the user (normally,
pushing the code into executable memory and so on).
It currently has three implementations:
It currently has two implementations:
1. Universal with [`wasmer-engine-universal`],
2. Native with [`wasmer-engine-dylib`],
3. Object with [`wasmer-engine-staticlib`].
2. Object with [`wasmer-engine-staticlib`].
## Example Implementation
@ -29,7 +28,6 @@ attributions of the project.
[`wasmer-engine-universal`]: https://github.com/wasmerio/wasmer/tree/master/lib/engine-universal
[`wasmer-engine-dylib`]: https://github.com/wasmerio/wasmer/tree/master/lib/engine-dylib
[`wasmer-engine-staticlib`]: https://github.com/wasmerio/wasmer/tree/master/lib/engine-staticlib
[`wasmer-engine-dummy`]: https://github.com/wasmerio/wasmer/tree/master/tests/lib/engine-dummy
[`wasmtime-api`]: https://crates.io/crates/wasmtime

View File

@ -13,7 +13,6 @@ attributions of the project.
[`wasmer-engine-universal`]: https://github.com/wasmerio/wasmer/tree/master/lib/engine-universal
[`wasmer-engine-dylib`]: https://github.com/wasmerio/wasmer/tree/master/lib/engine-dylib
[`wasmer-engine-staticlib`]: https://github.com/wasmerio/wasmer/tree/master/lib/engine-staticlib
[`wasmer-engine-dummy`]: https://github.com/wasmerio/wasmer/tree/master/tests/lib/engine-dummy
[`wasmtime-api`]: https://crates.io/crates/wasmtime

View File

@ -59,16 +59,6 @@ dep_graph = {
"wasmer-engine",
]
),
"wasmer-engine-dylib": set(
[
"wasmer-artifact",
"wasmer-types",
"wasmer-compiler",
"wasmer-vm",
"wasmer-engine",
"wasmer-object",
]
),
"wasmer-engine-staticlib": set(
[
"wasmer-artifact",
@ -91,7 +81,6 @@ dep_graph = {
"wasmer-compiler-cranelift",
"wasmer-compiler-llvm",
"wasmer-engine-universal",
"wasmer-engine-dylib",
]
),
"wasmer-vfs": set([]),
@ -110,7 +99,6 @@ dep_graph = {
"wasmer-emscripten",
"wasmer-engine",
"wasmer-engine-universal",
"wasmer-engine-dylib",
"wasmer-engine-staticlib",
"wasmer-middlewares",
"wasmer-wasi",
@ -129,7 +117,6 @@ dep_graph = {
"wasmer-emscripten",
"wasmer-engine",
"wasmer-engine-universal",
"wasmer-engine-dylib",
"wasmer-engine-staticlib",
"wasmer-vm",
"wasmer-wasi",
@ -159,7 +146,6 @@ location = {
"wasmer-compiler-llvm": "compiler-llvm",
"wasmer-engine": "engine",
"wasmer-engine-universal": "engine-universal",
"wasmer-engine-dylib": "engine-dylib",
"wasmer-engine-staticlib": "engine-staticlib",
"wasmer-cache": "cache",
"wasmer": "api",

View File

@ -10,7 +10,6 @@ pub enum Compiler {
#[derive(Clone, Debug, PartialEq)]
pub enum Engine {
Dylib,
Universal,
}
@ -61,14 +60,6 @@ impl Config {
#[cfg(not(feature = "engine"))]
compile_error!("Plese enable at least one engine via the features");
match &self.engine {
#[cfg(feature = "dylib")]
Engine::Dylib => {
let mut engine = wasmer_engine_dylib::Dylib::new(compiler_config);
if let Some(ref features) = self.features {
engine = engine.features(features.clone())
}
Box::new(engine.engine())
}
#[cfg(feature = "universal")]
Engine::Universal => {
let mut engine = wasmer_engine_universal::Universal::new(compiler_config);
@ -87,8 +78,6 @@ impl Config {
pub fn engine_headless(&self) -> Box<dyn WasmerEngine> {
match &self.engine {
#[cfg(feature = "dylib")]
Engine::Dylib => Box::new(wasmer_engine_dylib::Dylib::headless().engine()),
#[cfg(feature = "universal")]
Engine::Universal => Box::new(wasmer_engine_universal::Universal::headless().engine()),
#[allow(unreachable_patterns)]

View File

@ -42,6 +42,7 @@ pub fn run_wast(mut config: crate::Config, wast_path: &str) -> anyhow::Result<()
wast.allow_trap_message("uninitialized element 2", "uninitialized element");
// `liking.wast` has different wording but the same meaning
wast.allow_trap_message("out of bounds memory access", "memory out of bounds");
/*
if config.compiler == crate::Compiler::Cranelift && config.engine == crate::Engine::Dylib {
wast.allow_trap_message("call stack exhausted", "out of bounds memory access");
wast.allow_trap_message("indirect call type mismatch", "call stack exhausted");
@ -52,6 +53,7 @@ pub fn run_wast(mut config: crate::Config, wast_path: &str) -> anyhow::Result<()
wast.allow_trap_message("uninitialized element", "call stack exhausted");
wast.allow_trap_message("unreachable", "call stack exhausted");
}
*/
if cfg!(feature = "coverage") {
wast.disable_assert_and_exhaustion();
}

View File

@ -2,37 +2,27 @@
singlepass spec::multi_value # Singlepass has not implemented multivalue (functions that returns "structs"/"tuples")
singlepass spec::simd # Singlepass doesn't support yet SIMD (no one asked for this feature)
windows+dylib * # This might be trivial to fix?
musl+dylib * # Dynamic loading not supported in Musl
# Traps
## Traps. Tracing doesn't work properly in Singlepass
## Unwinding is not properly implemented in Singlepass
# Needs investigation
singlepass+aarch64+macos traps::test_trap_trace
dylib traps::test_trap_trace
cranelift+aarch64 traps::test_trap_trace
singlepass+aarch64+macos traps::test_trap_stack_overflow # Need to investigate
dylib traps::test_trap_stack_overflow # Need to investigate
cranelift+aarch64 traps::test_trap_stack_overflow # Need to investigate
singlepass+aarch64+macos traps::trap_display_pretty
llvm traps::trap_display_pretty
dylib traps::trap_display_pretty
cranelift+aarch64 traps::trap_display_pretty
singlepass+aarch64+macos traps::trap_display_multi_module
llvm traps::trap_display_multi_module
dylib traps::trap_display_multi_module
cranelift+aarch64 traps::trap_display_multi_module
singlepass traps::call_signature_mismatch # Need to investigate, get foo (a[0]:0x33) instead of 0x30 for inderect call
llvm traps::call_signature_mismatch
dylib traps::call_signature_mismatch
macos+aarch64 traps::call_signature_mismatch
singlepass+aarch64+macos traps::start_trap_pretty
llvm traps::start_trap_pretty
dylib traps::start_trap_pretty
cranelift+aarch64 traps::start_trap_pretty
singlepass multi_value_imports::dylib # Singlepass doesn't support multivalue
singlepass multi_value_imports::dynamic # Singlepass doesn't support multivalue
# Also neither LLVM nor Cranelift currently implement stack probing on AArch64.

View File

@ -22,7 +22,6 @@ impl Compiler {
#[derive(Debug, Copy, Clone)]
pub enum Engine {
Universal,
Dylib,
Staticlib,
}
@ -30,7 +29,6 @@ impl Engine {
pub const fn to_flag(self) -> &'static str {
match self {
Engine::Universal => "--universal",
Engine::Dylib => "--dylib",
Engine::Staticlib => "--staticlib",
}
}

View File

@ -115,7 +115,7 @@ impl Ignores {
arch = Some(alias.to_string());
}
// Engines
"universal" | "dylib" => {
"universal" => {
engine = Some(alias.to_string());
}
// Compilers

View File

@ -112,7 +112,6 @@ pub fn compiler_test(attrs: TokenStream, input: TokenStream) -> TokenStream {
let mod_name = ::quote::format_ident!("{}", compiler_name.to_lowercase());
let universal_engine_test =
construct_engine_test(func, compiler_name, "Universal", "universal");
let dylib_engine_test = construct_engine_test(func, compiler_name, "Dylib", "dylib");
let compiler_name_lowercase = compiler_name.to_lowercase();
quote! {
@ -121,7 +120,6 @@ pub fn compiler_test(attrs: TokenStream, input: TokenStream) -> TokenStream {
use super::*;
#universal_engine_test
#dylib_engine_test
}
}
};

View File

@ -63,15 +63,6 @@ gen_tests! {
crate::Compiler::Singlepass
))
}
#[test_log::test]
#[cold]
#[cfg(feature = "dylib")]
fn dylib() {
foo(crate::Config::new(
crate::Engine::Dylib,
crate::Compiler::Singlepass
))
}
}
#[cfg(feature = "cranelift")]
@ -86,15 +77,6 @@ gen_tests! {
crate::Compiler::Cranelift
))
}
#[test_log::test]
#[cold]
#[cfg(feature = "dylib")]
fn dylib() {
foo(crate::Config::new(
crate::Engine::Dylib,
crate::Compiler::Cranelift
))
}
}
#[cfg(feature = "llvm")]
@ -109,15 +91,6 @@ gen_tests! {
crate::Compiler::LLVM
))
}
#[test_log::test]
#[cold]
#[cfg(feature = "dylib")]
fn dylib() {
foo(crate::Config::new(
crate::Engine::Dylib,
crate::Compiler::LLVM
))
}
}
}
};

View File

@ -10,5 +10,4 @@ anyhow = "1.0"
target-lexicon = "0.12"
[features]
test-dylib = []
test-universal = []