mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-03 11:18:31 +00:00
Remove engine-dylib
This commit is contained in:
42
Cargo.lock
generated
42
Cargo.lock
generated
@@ -160,7 +160,7 @@ dependencies = [
|
|||||||
"regex",
|
"regex",
|
||||||
"rustc-hash",
|
"rustc-hash",
|
||||||
"shlex",
|
"shlex",
|
||||||
"which 3.1.1",
|
"which",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2796,7 +2796,6 @@ dependencies = [
|
|||||||
"wasmer-compiler-singlepass",
|
"wasmer-compiler-singlepass",
|
||||||
"wasmer-derive",
|
"wasmer-derive",
|
||||||
"wasmer-engine",
|
"wasmer-engine",
|
||||||
"wasmer-engine-dylib",
|
|
||||||
"wasmer-engine-universal",
|
"wasmer-engine-universal",
|
||||||
"wasmer-types",
|
"wasmer-types",
|
||||||
"wasmer-vm",
|
"wasmer-vm",
|
||||||
@@ -2826,7 +2825,6 @@ dependencies = [
|
|||||||
"wasmer-compiler-cranelift",
|
"wasmer-compiler-cranelift",
|
||||||
"wasmer-compiler-llvm",
|
"wasmer-compiler-llvm",
|
||||||
"wasmer-compiler-singlepass",
|
"wasmer-compiler-singlepass",
|
||||||
"wasmer-engine-dylib",
|
|
||||||
"wasmer-engine-universal",
|
"wasmer-engine-universal",
|
||||||
"wasmer-middlewares",
|
"wasmer-middlewares",
|
||||||
"wasmprinter",
|
"wasmprinter",
|
||||||
@@ -2853,7 +2851,6 @@ dependencies = [
|
|||||||
"wasmer-compiler-singlepass",
|
"wasmer-compiler-singlepass",
|
||||||
"wasmer-emscripten",
|
"wasmer-emscripten",
|
||||||
"wasmer-engine",
|
"wasmer-engine",
|
||||||
"wasmer-engine-dylib",
|
|
||||||
"wasmer-engine-staticlib",
|
"wasmer-engine-staticlib",
|
||||||
"wasmer-engine-universal",
|
"wasmer-engine-universal",
|
||||||
"wasmer-middlewares",
|
"wasmer-middlewares",
|
||||||
@@ -2873,7 +2870,6 @@ dependencies = [
|
|||||||
"thiserror",
|
"thiserror",
|
||||||
"wasmer",
|
"wasmer",
|
||||||
"wasmer-compiler-singlepass",
|
"wasmer-compiler-singlepass",
|
||||||
"wasmer-engine-dylib",
|
|
||||||
"wasmer-engine-universal",
|
"wasmer-engine-universal",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -2900,7 +2896,6 @@ dependencies = [
|
|||||||
"wasmer-compiler-singlepass",
|
"wasmer-compiler-singlepass",
|
||||||
"wasmer-emscripten",
|
"wasmer-emscripten",
|
||||||
"wasmer-engine",
|
"wasmer-engine",
|
||||||
"wasmer-engine-dylib",
|
|
||||||
"wasmer-engine-staticlib",
|
"wasmer-engine-staticlib",
|
||||||
"wasmer-engine-universal",
|
"wasmer-engine-universal",
|
||||||
"wasmer-types",
|
"wasmer-types",
|
||||||
@@ -3068,29 +3063,6 @@ dependencies = [
|
|||||||
"wasmer-vm",
|
"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]]
|
[[package]]
|
||||||
name = "wasmer-engine-staticlib"
|
name = "wasmer-engine-staticlib"
|
||||||
version = "2.3.0"
|
version = "2.3.0"
|
||||||
@@ -3352,7 +3324,6 @@ dependencies = [
|
|||||||
"wasmer-emscripten",
|
"wasmer-emscripten",
|
||||||
"wasmer-engine",
|
"wasmer-engine",
|
||||||
"wasmer-engine-dummy",
|
"wasmer-engine-dummy",
|
||||||
"wasmer-engine-dylib",
|
|
||||||
"wasmer-engine-staticlib",
|
"wasmer-engine-staticlib",
|
||||||
"wasmer-engine-universal",
|
"wasmer-engine-universal",
|
||||||
"wasmer-middlewares",
|
"wasmer-middlewares",
|
||||||
@@ -3514,17 +3485,6 @@ dependencies = [
|
|||||||
"libc",
|
"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]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
|
|||||||
17
Cargo.toml
17
Cargo.toml
@@ -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-emscripten = { version = "=2.3.0", path = "lib/emscripten", optional = true }
|
||||||
wasmer-engine = { version = "=2.3.0", path = "lib/engine" }
|
wasmer-engine = { version = "=2.3.0", path = "lib/engine" }
|
||||||
wasmer-engine-universal = { version = "=2.3.0", path = "lib/engine-universal", optional = true }
|
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-engine-staticlib = { version = "=2.3.0", path = "lib/engine-staticlib", optional = true }
|
||||||
wasmer-wasi = { version = "=2.3.0", path = "lib/wasi", 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 }
|
wasmer-wast = { version = "=2.3.0", path = "tests/lib/wast", optional = true }
|
||||||
@@ -43,7 +42,6 @@ members = [
|
|||||||
"lib/emscripten",
|
"lib/emscripten",
|
||||||
"lib/engine",
|
"lib/engine",
|
||||||
"lib/engine-universal",
|
"lib/engine-universal",
|
||||||
"lib/engine-dylib",
|
|
||||||
"lib/engine-staticlib",
|
"lib/engine-staticlib",
|
||||||
"lib/object",
|
"lib/object",
|
||||||
"lib/vfs",
|
"lib/vfs",
|
||||||
@@ -91,7 +89,6 @@ default = [
|
|||||||
"wat",
|
"wat",
|
||||||
"wast",
|
"wast",
|
||||||
"universal",
|
"universal",
|
||||||
"dylib",
|
|
||||||
"staticlib",
|
"staticlib",
|
||||||
"cache",
|
"cache",
|
||||||
"wasi",
|
"wasi",
|
||||||
@@ -103,10 +100,6 @@ universal = [
|
|||||||
"wasmer-engine-universal",
|
"wasmer-engine-universal",
|
||||||
"engine",
|
"engine",
|
||||||
]
|
]
|
||||||
dylib = [
|
|
||||||
"wasmer-engine-dylib",
|
|
||||||
"engine",
|
|
||||||
]
|
|
||||||
staticlib = [
|
staticlib = [
|
||||||
"wasmer-engine-staticlib",
|
"wasmer-engine-staticlib",
|
||||||
"engine",
|
"engine",
|
||||||
@@ -120,7 +113,6 @@ compiler = [
|
|||||||
"wasmer/compiler",
|
"wasmer/compiler",
|
||||||
"wasmer-compiler/translator",
|
"wasmer-compiler/translator",
|
||||||
"wasmer-engine-universal/compiler",
|
"wasmer-engine-universal/compiler",
|
||||||
"wasmer-engine-dylib/compiler",
|
|
||||||
"wasmer-engine-staticlib/compiler",
|
"wasmer-engine-staticlib/compiler",
|
||||||
]
|
]
|
||||||
singlepass = [
|
singlepass = [
|
||||||
@@ -148,10 +140,6 @@ test-llvm = [
|
|||||||
"llvm",
|
"llvm",
|
||||||
]
|
]
|
||||||
|
|
||||||
test-dylib = [
|
|
||||||
"dylib",
|
|
||||||
"test-generator/test-dylib",
|
|
||||||
]
|
|
||||||
test-universal = [
|
test-universal = [
|
||||||
"universal",
|
"universal",
|
||||||
"test-generator/test-universal",
|
"test-generator/test-universal",
|
||||||
@@ -178,11 +166,6 @@ name = "engine-universal"
|
|||||||
path = "examples/engine_universal.rs"
|
path = "examples/engine_universal.rs"
|
||||||
required-features = ["cranelift"]
|
required-features = ["cranelift"]
|
||||||
|
|
||||||
[[example]]
|
|
||||||
name = "engine-dylib"
|
|
||||||
path = "examples/engine_dylib.rs"
|
|
||||||
required-features = ["cranelift"]
|
|
||||||
|
|
||||||
[[example]]
|
[[example]]
|
||||||
name = "engine-headless"
|
name = "engine-headless"
|
||||||
path = "examples/engine_headless.rs"
|
path = "examples/engine_headless.rs"
|
||||||
|
|||||||
72
Makefile
72
Makefile
@@ -13,29 +13,20 @@ SHELL=/usr/bin/env bash
|
|||||||
# | Compiler ⨯ Engine ⨯ Platform ⨯ Architecture ⨯ libc |
|
# | Compiler ⨯ Engine ⨯ Platform ⨯ Architecture ⨯ libc |
|
||||||
# |------------|-----------|----------|--------------|-------|
|
# |------------|-----------|----------|--------------|-------|
|
||||||
# | Cranelift | Universal | Linux | amd64 | glibc |
|
# | Cranelift | Universal | Linux | amd64 | glibc |
|
||||||
# | LLVM | Dylib | Darwin | aarch64 | musl |
|
# | LLVM | Staticlib | Darwin | aarch64 | musl |
|
||||||
# | Singlepass | Staticlib | Windows | | |
|
# | Singlepass | | Windows | | |
|
||||||
# |------------|-----------|----------|--------------|-------|
|
# |------------|-----------|----------|--------------|-------|
|
||||||
#
|
#
|
||||||
# Here is what works and what doesn't:
|
# Here is what works and what doesn't:
|
||||||
#
|
#
|
||||||
# * Cranelift with the Universal engine works everywhere,
|
# * 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`,
|
# * LLVM with the Universal engine works on Linux+Darwin/`amd64`,
|
||||||
# but it doesn't work on */`aarch64` or Windows/*.
|
# 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
|
# * Singlepass with the Universal engine works on Linux+Darwin/`amd64`, but
|
||||||
# it doesn't work on */`aarch64` or Windows/*.
|
# 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
|
# * Windows isn't tested on `aarch64`, that's why we consider it's not
|
||||||
# working, but it might possibly be.
|
# working, but it might possibly be.
|
||||||
|
|
||||||
@@ -217,18 +208,6 @@ compilers_engines :=
|
|||||||
|
|
||||||
ifeq ($(ENABLE_CRANELIFT), 1)
|
ifeq ($(ENABLE_CRANELIFT), 1)
|
||||||
compilers_engines += cranelift-universal
|
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
|
endif
|
||||||
|
|
||||||
##
|
##
|
||||||
@@ -239,10 +218,8 @@ ifeq ($(ENABLE_LLVM), 1)
|
|||||||
ifneq (, $(filter 1, $(IS_WINDOWS) $(IS_DARWIN) $(IS_LINUX)))
|
ifneq (, $(filter 1, $(IS_WINDOWS) $(IS_DARWIN) $(IS_LINUX)))
|
||||||
ifeq ($(IS_AMD64), 1)
|
ifeq ($(IS_AMD64), 1)
|
||||||
compilers_engines += llvm-universal
|
compilers_engines += llvm-universal
|
||||||
compilers_engines += llvm-dylib
|
|
||||||
else ifeq ($(IS_AARCH64), 1)
|
else ifeq ($(IS_AARCH64), 1)
|
||||||
compilers_engines += llvm-universal
|
compilers_engines += llvm-universal
|
||||||
compilers_engines += llvm-dylib
|
|
||||||
endif
|
endif
|
||||||
endif
|
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.
|
# LLVM for the moment because it causes the linker to fail since LLVM is not statically linked.
|
||||||
# TODO: Reenable LLVM in C-API
|
# TODO: Reenable LLVM in C-API
|
||||||
capi_compiler_features := --features $(subst $(space),$(comma),$(filter-out llvm, $(compilers)))
|
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)
|
# We exclude singlepass-universal because it doesn't support multivalue (required in wasm-c-api tests)
|
||||||
capi_compilers_engines_exclude += singlepass-universal
|
capi_compilers_engines_exclude += singlepass-universal
|
||||||
@@ -444,57 +421,45 @@ build-docs-capi: capi-setup
|
|||||||
# when generating the documentation, we rename it to its
|
# when generating the documentation, we rename it to its
|
||||||
# crate's name. Then we restore the lib's name.
|
# 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
|
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
|
sed "$(SEDI)" -e 's/name = "wasmer_c_api" # ##lib.name##/name = "wasmer" # ##lib.name##/' lib/c-api/Cargo.toml
|
||||||
|
|
||||||
build-capi: capi-setup
|
build-capi: capi-setup
|
||||||
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
|
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
|
build-capi-singlepass: capi-setup
|
||||||
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
|
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
|
build-capi-singlepass-universal: capi-setup
|
||||||
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
|
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
|
||||||
--no-default-features --features wat,universal,singlepass,wasi,middlewares
|
--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
|
build-capi-singlepass-staticlib: capi-setup
|
||||||
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
|
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
|
||||||
--no-default-features --features wat,staticlib,singlepass,wasi,middlewares
|
--no-default-features --features wat,staticlib,singlepass,wasi,middlewares
|
||||||
|
|
||||||
build-capi-cranelift: capi-setup
|
build-capi-cranelift: capi-setup
|
||||||
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
|
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
|
build-capi-cranelift-universal: capi-setup
|
||||||
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
|
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
|
||||||
--no-default-features --features wat,universal,cranelift,wasi,middlewares
|
--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
|
build-capi-cranelift-staticlib: capi-setup
|
||||||
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
|
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
|
build-capi-llvm: capi-setup
|
||||||
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
|
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
|
build-capi-llvm-universal: capi-setup
|
||||||
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
|
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
|
||||||
--no-default-features --features wat,universal,llvm,wasi,middlewares
|
--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
|
build-capi-llvm-staticlib: capi-setup
|
||||||
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
|
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
|
||||||
--no-default-features --features wat,staticlib,llvm,wasi,middlewares
|
--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 \
|
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
|
||||||
--no-default-features --features universal,wasi
|
--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
|
build-capi-headless-staticlib: capi-setup
|
||||||
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
|
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
|
||||||
--no-default-features --features staticlib,wasi
|
--no-default-features --features staticlib,wasi
|
||||||
|
|
||||||
build-capi-headless-all: capi-setup
|
build-capi-headless-all: capi-setup
|
||||||
RUSTFLAGS="${RUSTFLAGS}" $(CARGO_BINARY) build $(CARGO_TARGET) --manifest-path lib/c-api/Cargo.toml --release \
|
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
|
build-capi-headless-ios: capi-setup
|
||||||
RUSTFLAGS="${RUSTFLAGS}" cargo lipo --manifest-path lib/c-api/Cargo.toml --release \
|
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-compilers-compat: $(foreach compiler,$(compilers),test-$(compiler))
|
||||||
|
|
||||||
test-singlepass-dylib:
|
|
||||||
$(CARGO_BINARY) test $(CARGO_TARGET) --release --tests $(compiler_features) -- singlepass::dylib
|
|
||||||
|
|
||||||
test-singlepass-universal:
|
test-singlepass-universal:
|
||||||
$(CARGO_BINARY) test $(CARGO_TARGET) --release --tests $(compiler_features) -- 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:
|
test-cranelift-universal:
|
||||||
$(CARGO_BINARY) test $(CARGO_TARGET) --release --tests $(compiler_features) -- 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:
|
test-llvm-universal:
|
||||||
$(CARGO_BINARY) test $(CARGO_TARGET) --release --tests $(compiler_features) -- 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-%:
|
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 \
|
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-capi-integration-%:
|
||||||
# Test the Wasmer C API tests for C
|
# Test the Wasmer C API tests for C
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ digraph dependencies {
|
|||||||
n1 [label="wasmer-compiler", color=orange];
|
n1 [label="wasmer-compiler", color=orange];
|
||||||
n5 [label="wasmer-engine", color=orange];
|
n5 [label="wasmer-engine", color=orange];
|
||||||
n6 [label="wasmer-engine-universal", color=orange];
|
n6 [label="wasmer-engine-universal", color=orange];
|
||||||
n7 [label="wasmer-engine-dylib", color=orange];
|
|
||||||
n8 [label="wasmer-types", color=orange];
|
n8 [label="wasmer-types", color=orange];
|
||||||
n9 [label="wasmer-vm", color=orange];
|
n9 [label="wasmer-vm", color=orange];
|
||||||
n10 [label="wasmer-c-api", color=orange];
|
n10 [label="wasmer-c-api", color=orange];
|
||||||
@@ -29,7 +28,6 @@ digraph dependencies {
|
|||||||
color=brown;
|
color=brown;
|
||||||
|
|
||||||
n6 [label="wasmer-engine-universal", color=orange];
|
n6 [label="wasmer-engine-universal", color=orange];
|
||||||
n7 [label="wasmer-engine-dylib", color=orange];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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"/>
|
<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"/>
|
<polygon fill="orange" stroke="orange" points="349.79,-323.99 339.24,-323.02 346.88,-330.36 349.79,-323.99"/>
|
||||||
</g>
|
</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-engine-dylib</text>
|
|
||||||
</g>
|
|
||||||
<!-- n0->n7 -->
|
|
||||||
<g id="edge13" class="edge">
|
|
||||||
<title>n0->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 -->
|
<!-- n2 -->
|
||||||
<g id="node13" class="node">
|
<g id="node13" class="node">
|
||||||
<title>n2</title>
|
<title>n2</title>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 11 KiB |
@@ -236,24 +236,7 @@ example.
|
|||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
2. [**Dylib engine**][engine-dylib], explains what a Dylib engine
|
2. [**Headless engines**][engine-headless], explains what a headless
|
||||||
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
|
|
||||||
engine is, what problem it does solve, and what are the benefits of
|
engine is, what problem it does solve, and what are the benefits of
|
||||||
it. The example completes itself with the instantiation of a
|
it. The example completes itself with the instantiation of a
|
||||||
pre-compiled Wasm module, and finally, by calling an exported
|
pre-compiled Wasm module, and finally, by calling an exported
|
||||||
@@ -376,7 +359,6 @@ example.
|
|||||||
|
|
||||||
[hello-world]: ./hello_world.rs
|
[hello-world]: ./hello_world.rs
|
||||||
[engine-universal]: ./engine_universal.rs
|
[engine-universal]: ./engine_universal.rs
|
||||||
[engine-dylib]: ./engine_dylib.rs
|
|
||||||
[engine-headless]: ./engine_headless.rs
|
[engine-headless]: ./engine_headless.rs
|
||||||
[compiler-singlepass]: ./compiler_singlepass.rs
|
[compiler-singlepass]: ./compiler_singlepass.rs
|
||||||
[compiler-cranelift]: ./compiler_cranelift.rs
|
[compiler-cranelift]: ./compiler_cranelift.rs
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ use std::str::FromStr;
|
|||||||
use wasmer::{wat2wasm, Module, RuntimeError, Store};
|
use wasmer::{wat2wasm, Module, RuntimeError, Store};
|
||||||
use wasmer_compiler::{CpuFeature, Target, Triple};
|
use wasmer_compiler::{CpuFeature, Target, Triple};
|
||||||
use wasmer_compiler_cranelift::Cranelift;
|
use wasmer_compiler_cranelift::Cranelift;
|
||||||
use wasmer_engine_dylib::Dylib;
|
use wasmer_engine_universal::Universal;
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
// Let's declare the Wasm module with the text representation.
|
// 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.
|
// 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.
|
// That's where we specify the target for the compiler.
|
||||||
//
|
//
|
||||||
// Use the Dylib engine.
|
// Use the Universal engine.
|
||||||
let engine = Dylib::new(compiler_config)
|
let engine = Universal::new(compiler_config)
|
||||||
// Here we go.
|
// Here we go.
|
||||||
// Pass the target to the engine! The engine will share
|
// Pass the target to the engine! The engine will share
|
||||||
// this information with the compiler.
|
// this information with the compiler.
|
||||||
|
|||||||
@@ -20,67 +20,71 @@
|
|||||||
|
|
||||||
use wasmer::{imports, wat2wasm, Instance, Module, Store, Value};
|
use wasmer::{imports, wat2wasm, Instance, Module, Store, Value};
|
||||||
use wasmer_compiler_cranelift::Cranelift;
|
use wasmer_compiler_cranelift::Cranelift;
|
||||||
|
/*
|
||||||
use wasmer_engine_dylib::Dylib;
|
use wasmer_engine_dylib::Dylib;
|
||||||
|
*/
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
// Let's declare the Wasm module with the text representation.
|
/*
|
||||||
let wasm_bytes = wat2wasm(
|
// Let's declare the Wasm module with the text representation.
|
||||||
r#"
|
let wasm_bytes = wat2wasm(
|
||||||
(module
|
r#"
|
||||||
(type $sum_t (func (param i32 i32) (result i32)))
|
(module
|
||||||
(func $sum_f (type $sum_t) (param $x i32) (param $y i32) (result i32)
|
(type $sum_t (func (param i32 i32) (result i32)))
|
||||||
local.get $x
|
(func $sum_f (type $sum_t) (param $x i32) (param $y i32) (result i32)
|
||||||
local.get $y
|
local.get $x
|
||||||
i32.add)
|
local.get $y
|
||||||
(export "sum" (func $sum_f)))
|
i32.add)
|
||||||
"#
|
(export "sum" (func $sum_f)))
|
||||||
.as_bytes(),
|
"#
|
||||||
)?;
|
.as_bytes(),
|
||||||
|
)?;
|
||||||
|
|
||||||
// Define a compiler configuration.
|
// Define a compiler configuration.
|
||||||
//
|
//
|
||||||
// In this situation, the compiler is
|
// In this situation, the compiler is
|
||||||
// `wasmer_compiler_cranelift`. The compiler is responsible to
|
// `wasmer_compiler_cranelift`. The compiler is responsible to
|
||||||
// compile the Wasm module into executable code.
|
// compile the Wasm module into executable code.
|
||||||
let compiler_config = Cranelift::default();
|
let compiler_config = Cranelift::default();
|
||||||
|
|
||||||
println!("Creating Dylib engine...");
|
println!("Creating Dylib engine...");
|
||||||
// Define the engine that will drive everything.
|
// Define the engine that will drive everything.
|
||||||
//
|
//
|
||||||
// In this case, the engine is `wasmer_engine_dylib` which means
|
// In this case, the engine is `wasmer_engine_dylib` which means
|
||||||
// that a shared object is going to be generated.
|
// that a shared object is going to be generated.
|
||||||
let engine = Dylib::new(compiler_config).engine();
|
let engine = Dylib::new(compiler_config).engine();
|
||||||
|
|
||||||
// Create a store, that holds the engine.
|
// Create a store, that holds the engine.
|
||||||
let store = Store::new(&engine);
|
let store = Store::new(&engine);
|
||||||
|
|
||||||
println!("Compiling module...");
|
println!("Compiling module...");
|
||||||
// Here we go.
|
// Here we go.
|
||||||
//
|
//
|
||||||
// Let's compile the Wasm module. It is at this step that the Wasm
|
// Let's compile the Wasm module. It is at this step that the Wasm
|
||||||
// text is transformed into Wasm bytes (if necessary), and then
|
// text is transformed into Wasm bytes (if necessary), and then
|
||||||
// compiled to executable code by the compiler, which is then
|
// compiled to executable code by the compiler, which is then
|
||||||
// stored into a shared object by the engine.
|
// stored into a shared object by the engine.
|
||||||
let module = Module::new(&store, wasm_bytes)?;
|
let module = Module::new(&store, wasm_bytes)?;
|
||||||
|
|
||||||
// Congrats, the Wasm module is compiled! Now let's execute it for
|
// Congrats, the Wasm module is compiled! Now let's execute it for
|
||||||
// the sake of having a complete example.
|
// the sake of having a complete example.
|
||||||
|
|
||||||
// Create an import object. Since our Wasm module didn't declare
|
// Create an import object. Since our Wasm module didn't declare
|
||||||
// any imports, it's an empty object.
|
// any imports, it's an empty object.
|
||||||
let import_object = imports! {};
|
let import_object = imports! {};
|
||||||
|
|
||||||
println!("Instantiating module...");
|
println!("Instantiating module...");
|
||||||
// And here we go again. Let's instantiate the Wasm module.
|
// And here we go again. Let's instantiate the Wasm module.
|
||||||
let instance = Instance::new(&module, &import_object)?;
|
let instance = Instance::new(&module, &import_object)?;
|
||||||
|
|
||||||
println!("Calling `sum` function...");
|
println!("Calling `sum` function...");
|
||||||
// The Wasm module exports a function called `sum`.
|
// The Wasm module exports a function called `sum`.
|
||||||
let sum = instance.exports.get_function("sum")?;
|
let sum = instance.exports.get_function("sum")?;
|
||||||
let results = sum.call(&[Value::I32(1), Value::I32(2)])?;
|
let results = sum.call(&[Value::I32(1), Value::I32(2)])?;
|
||||||
|
|
||||||
println!("Results: {:?}", results);
|
println!("Results: {:?}", results);
|
||||||
assert_eq!(results.to_vec(), vec![Value::I32(3)]);
|
assert_eq!(results.to_vec(), vec![Value::I32(3)]);
|
||||||
|
*/
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,10 +8,9 @@
|
|||||||
//! What problem does it solve, and what does it mean?
|
//! What problem does it solve, and what does it mean?
|
||||||
//!
|
//!
|
||||||
//! Once a Wasm module is compiled into executable code and stored
|
//! Once a Wasm module is compiled into executable code and stored
|
||||||
//! somewhere (e.g. in memory with the Universal engine, or in a
|
//! somewhere (e.g. in memory with the Universal engine), the module
|
||||||
//! shared object file with the Dylib engine), the module can be
|
//! can be instantiated and executed. But imagine for a second the
|
||||||
//! instantiated and executed. But imagine for a second the following
|
//! following scenario:
|
||||||
//! scenario:
|
|
||||||
//!
|
//!
|
||||||
//! * Modules are compiled ahead of time, to be instantiated later
|
//! * Modules are compiled ahead of time, to be instantiated later
|
||||||
//! on.
|
//! on.
|
||||||
@@ -53,7 +52,7 @@ use wasmer::Module;
|
|||||||
use wasmer::Store;
|
use wasmer::Store;
|
||||||
use wasmer::Value;
|
use wasmer::Value;
|
||||||
use wasmer_compiler_cranelift::Cranelift;
|
use wasmer_compiler_cranelift::Cranelift;
|
||||||
use wasmer_engine_dylib::Dylib;
|
use wasmer_engine_universal::Universal;
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
// First step, let's compile the Wasm module and serialize it.
|
// 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.
|
// compile the Wasm module into executable code.
|
||||||
let compiler_config = Cranelift::default();
|
let compiler_config = Cranelift::default();
|
||||||
|
|
||||||
println!("Creating Dylib engine...");
|
println!("Creating univesral engine...");
|
||||||
// Define the engine that will drive everything.
|
// Define the engine that will drive everything.
|
||||||
//
|
let engine = Universal::new(compiler_config).engine();
|
||||||
// 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();
|
|
||||||
|
|
||||||
// Create a store, that holds the engine.
|
// Create a store, that holds the engine.
|
||||||
let store = Store::new(&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
|
// Second step, deserialize the compiled Wasm module, and execute
|
||||||
// it, for example with Wasmer without a compiler.
|
// it, for example with Wasmer without a compiler.
|
||||||
{
|
{
|
||||||
println!("Creating headless Dylib engine...");
|
println!("Creating headless Universal engine...");
|
||||||
// We create a headless Dylib engine.
|
// We create a headless Universal engine.
|
||||||
let engine = Dylib::headless().engine();
|
let engine = Universal::headless().engine();
|
||||||
let store = Store::new(&engine);
|
let store = Store::new(&engine);
|
||||||
|
|
||||||
println!("Deserializing module...");
|
println!("Deserializing module...");
|
||||||
|
|||||||
@@ -17,49 +17,53 @@ use std::str::FromStr;
|
|||||||
use wasmer::{wat2wasm, Module, RuntimeError, Store};
|
use wasmer::{wat2wasm, Module, RuntimeError, Store};
|
||||||
use wasmer_compiler::{CpuFeature, Target, Triple};
|
use wasmer_compiler::{CpuFeature, Target, Triple};
|
||||||
use wasmer_compiler_cranelift::Cranelift;
|
use wasmer_compiler_cranelift::Cranelift;
|
||||||
|
/*
|
||||||
use wasmer_engine_dylib::Dylib;
|
use wasmer_engine_dylib::Dylib;
|
||||||
|
*/
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
// Let's declare the Wasm module with the text representation.
|
/*
|
||||||
let wasm_bytes = wat2wasm(
|
// Let's declare the Wasm module with the text representation.
|
||||||
r#"
|
let wasm_bytes = wat2wasm(
|
||||||
(module
|
r#"
|
||||||
(type $sum_t (func (param i32 i32) (result i32)))
|
(module
|
||||||
(func $sum_f (type $sum_t) (param $x i32) (param $y i32) (result i32)
|
(type $sum_t (func (param i32 i32) (result i32)))
|
||||||
local.get $x
|
(func $sum_f (type $sum_t) (param $x i32) (param $y i32) (result i32)
|
||||||
local.get $y
|
local.get $x
|
||||||
i32.add)
|
local.get $y
|
||||||
(export "sum" (func $sum_f)))
|
i32.add)
|
||||||
"#
|
(export "sum" (func $sum_f)))
|
||||||
.as_bytes(),
|
"#
|
||||||
)?;
|
.as_bytes(),
|
||||||
|
)?;
|
||||||
|
|
||||||
// Create a compiler for iOS
|
// Create a compiler for iOS
|
||||||
let compiler_config = Cranelift::default();
|
let compiler_config = Cranelift::default();
|
||||||
// Change it to `x86_64-apple-ios` if you want to target the iOS simulator
|
// Change it to `x86_64-apple-ios` if you want to target the iOS simulator
|
||||||
let triple = Triple::from_str("aarch64-apple-ios")
|
let triple = Triple::from_str("aarch64-apple-ios")
|
||||||
.map_err(|error| RuntimeError::new(error.to_string()))?;
|
.map_err(|error| RuntimeError::new(error.to_string()))?;
|
||||||
|
|
||||||
// Let's build the target.
|
// Let's build the target.
|
||||||
let mut cpu_feature = CpuFeature::set();
|
let mut cpu_feature = CpuFeature::set();
|
||||||
cpu_feature.insert(CpuFeature::from_str("sse2")?);
|
cpu_feature.insert(CpuFeature::from_str("sse2")?);
|
||||||
let target = Target::new(triple, cpu_feature);
|
let target = Target::new(triple, cpu_feature);
|
||||||
println!("Chosen target: {:?}", target);
|
println!("Chosen target: {:?}", target);
|
||||||
|
|
||||||
println!("Creating Dylib engine...");
|
println!("Creating Dylib engine...");
|
||||||
let engine = Dylib::new(compiler_config).target(target).engine();
|
let engine = Dylib::new(compiler_config).target(target).engine();
|
||||||
|
|
||||||
// Create a store, that holds the engine.
|
// Create a store, that holds the engine.
|
||||||
let store = Store::new(&engine);
|
let store = Store::new(&engine);
|
||||||
|
|
||||||
println!("Compiling module...");
|
println!("Compiling module...");
|
||||||
// Let's compile the Wasm module.
|
// Let's compile the Wasm module.
|
||||||
let module = Module::new(&store, wasm_bytes)?;
|
let module = Module::new(&store, wasm_bytes)?;
|
||||||
// Here we go. Let's serialize the compiled Wasm module in a
|
// Here we go. Let's serialize the compiled Wasm module in a
|
||||||
// file.
|
// file.
|
||||||
println!("Serializing module...");
|
println!("Serializing module...");
|
||||||
let dylib_file = Path::new("./sum.dylib");
|
let dylib_file = Path::new("./sum.dylib");
|
||||||
module.serialize_to_file(dylib_file)?;
|
module.serialize_to_file(dylib_file)?;
|
||||||
|
*/
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ wasmer-compiler-cranelift = { path = "../lib/compiler-cranelift", optional = tru
|
|||||||
wasmer-compiler-llvm = { path = "../lib/compiler-llvm", optional = true }
|
wasmer-compiler-llvm = { path = "../lib/compiler-llvm", optional = true }
|
||||||
wasmer-compiler-singlepass = { path = "../lib/compiler-singlepass", optional = true }
|
wasmer-compiler-singlepass = { path = "../lib/compiler-singlepass", optional = true }
|
||||||
wasmer-engine-universal = { path = "../lib/engine-universal", 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" }
|
wasmer-middlewares = { path = "../lib/middlewares" }
|
||||||
wasmprinter = "0.2"
|
wasmprinter = "0.2"
|
||||||
|
|
||||||
@@ -26,7 +25,6 @@ cranelift = [ "wasmer-compiler-cranelift" ]
|
|||||||
llvm = [ "wasmer-compiler-llvm" ]
|
llvm = [ "wasmer-compiler-llvm" ]
|
||||||
singlepass = [ "wasmer-compiler-singlepass" ]
|
singlepass = [ "wasmer-compiler-singlepass" ]
|
||||||
universal = [ "wasmer-engine-universal" ]
|
universal = [ "wasmer-engine-universal" ]
|
||||||
dylib = [ "wasmer-engine-dylib" ]
|
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "equivalence_universal"
|
name = "equivalence_universal"
|
||||||
@@ -53,12 +51,7 @@ name = "metering"
|
|||||||
path = "fuzz_targets/metering.rs"
|
path = "fuzz_targets/metering.rs"
|
||||||
required-features = ["universal", "cranelift"]
|
required-features = ["universal", "cranelift"]
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "dylib_cranelift"
|
|
||||||
path = "fuzz_targets/dylib_cranelift.rs"
|
|
||||||
required-features = ["dylib", "cranelift"]
|
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "deterministic"
|
name = "deterministic"
|
||||||
path = "fuzz_targets/deterministic.rs"
|
path = "fuzz_targets/deterministic.rs"
|
||||||
required-features = ["universal", "dylib", "cranelift", "llvm", "singlepass"]
|
required-features = ["universal", "cranelift", "llvm", "singlepass"]
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ use wasmer::{CompilerConfig, Engine, Module, Store};
|
|||||||
use wasmer_compiler_cranelift::Cranelift;
|
use wasmer_compiler_cranelift::Cranelift;
|
||||||
use wasmer_compiler_llvm::LLVM;
|
use wasmer_compiler_llvm::LLVM;
|
||||||
use wasmer_compiler_singlepass::Singlepass;
|
use wasmer_compiler_singlepass::Singlepass;
|
||||||
use wasmer_engine_dylib::Dylib;
|
|
||||||
use wasmer_engine_universal::Universal;
|
use wasmer_engine_universal::Universal;
|
||||||
|
|
||||||
#[derive(Arbitrary, Debug, Default, Copy, Clone)]
|
#[derive(Arbitrary, Debug, Default, Copy, Clone)]
|
||||||
@@ -51,11 +50,6 @@ fuzz_target!(|module: ConfiguredModule<NoImportsConfig>| {
|
|||||||
Universal::new(compiler.clone()).engine(),
|
Universal::new(compiler.clone()).engine(),
|
||||||
&wasm_bytes,
|
&wasm_bytes,
|
||||||
);
|
);
|
||||||
//compile_and_compare(
|
|
||||||
// "dylib-cranelift",
|
|
||||||
// Dylib::new(compiler).engine(),
|
|
||||||
// &wasm_bytes,
|
|
||||||
//);
|
|
||||||
|
|
||||||
let mut compiler = LLVM::default();
|
let mut compiler = LLVM::default();
|
||||||
compiler.canonicalize_nans(true);
|
compiler.canonicalize_nans(true);
|
||||||
@@ -65,7 +59,6 @@ fuzz_target!(|module: ConfiguredModule<NoImportsConfig>| {
|
|||||||
Universal::new(compiler.clone()).engine(),
|
Universal::new(compiler.clone()).engine(),
|
||||||
&wasm_bytes,
|
&wasm_bytes,
|
||||||
);
|
);
|
||||||
//compile_and_compare("dylib-llvm", Dylib::new(compiler).engine(), &wasm_bytes);
|
|
||||||
|
|
||||||
let compiler = Singlepass::default();
|
let compiler = Singlepass::default();
|
||||||
compile_and_compare(
|
compile_and_compare(
|
||||||
@@ -73,9 +66,4 @@ fuzz_target!(|module: ConfiguredModule<NoImportsConfig>| {
|
|||||||
Universal::new(compiler.clone()).engine(),
|
Universal::new(compiler.clone()).engine(),
|
||||||
&wasm_bytes,
|
&wasm_bytes,
|
||||||
);
|
);
|
||||||
//compile_and_compare(
|
|
||||||
// "dylib-singlepass",
|
|
||||||
// Dylib::new(compiler).engine(),
|
|
||||||
// &wasm_bytes,
|
|
||||||
//);
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
@@ -34,9 +34,6 @@ composed of a set of crates. We can group them as follows:
|
|||||||
differ:
|
differ:
|
||||||
* `engine-universal` — stores the code in a custom file format, and
|
* `engine-universal` — stores the code in a custom file format, and
|
||||||
loads it in memory,
|
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
|
* `engine-staticlib` — stores executable code in a native static
|
||||||
object library, in addition to emitting a C header file, which
|
object library, in addition to emitting a C header file, which
|
||||||
both can be linked against a sandboxed WebAssembly runtime
|
both can be linked against a sandboxed WebAssembly runtime
|
||||||
|
|||||||
@@ -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-cranelift = { path = "../compiler-cranelift", version = "=2.3.0", optional = true }
|
||||||
wasmer-compiler-llvm = { path = "../compiler-llvm", 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-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.
|
# - Mandatory dependencies for `sys` on Windows.
|
||||||
[target.'cfg(all(not(target_arch = "wasm32"), target_os = "windows"))'.dependencies]
|
[target.'cfg(all(not(target_arch = "wasm32"), target_os = "windows"))'.dependencies]
|
||||||
winapi = "0.3"
|
winapi = "0.3"
|
||||||
@@ -93,7 +92,6 @@ compiler = [
|
|||||||
"sys",
|
"sys",
|
||||||
"wasmer-compiler/translator",
|
"wasmer-compiler/translator",
|
||||||
"wasmer-engine-universal/compiler",
|
"wasmer-engine-universal/compiler",
|
||||||
"wasmer-engine-dylib/compiler",
|
|
||||||
]
|
]
|
||||||
singlepass = [
|
singlepass = [
|
||||||
"compiler",
|
"compiler",
|
||||||
@@ -126,19 +124,11 @@ engine = ["sys"]
|
|||||||
"engine",
|
"engine",
|
||||||
"wasmer-engine-universal",
|
"wasmer-engine-universal",
|
||||||
]
|
]
|
||||||
dylib = [
|
|
||||||
"engine",
|
|
||||||
"wasmer-engine-dylib",
|
|
||||||
]
|
|
||||||
default-engine = []
|
default-engine = []
|
||||||
default-universal = [
|
default-universal = [
|
||||||
"default-engine",
|
"default-engine",
|
||||||
"universal",
|
"universal",
|
||||||
]
|
]
|
||||||
default-dylib = [
|
|
||||||
"default-engine",
|
|
||||||
"dylib",
|
|
||||||
]
|
|
||||||
# - Experimental / in-development features
|
# - Experimental / in-development features
|
||||||
experimental-reference-types-extern-ref = [
|
experimental-reference-types-extern-ref = [
|
||||||
"sys",
|
"sys",
|
||||||
@@ -146,7 +136,6 @@ experimental-reference-types-extern-ref = [
|
|||||||
]
|
]
|
||||||
# - Deprecated features.
|
# - Deprecated features.
|
||||||
jit = ["universal"]
|
jit = ["universal"]
|
||||||
native = ["dylib"]
|
|
||||||
|
|
||||||
# Features for `js`.
|
# Features for `js`.
|
||||||
js = []
|
js = []
|
||||||
@@ -157,4 +146,4 @@ wasm-types-polyfill = ["js", "wasmparser"]
|
|||||||
js-serializable-module = []
|
js-serializable-module = []
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[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"]
|
||||||
|
|||||||
@@ -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
|
compilation process and to store the generated executable code
|
||||||
somewhere, either:
|
somewhere, either:
|
||||||
* in-memory (with [`wasmer-engine-universal`]),
|
* 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 a native static object file (with [`wasmer-engine-staticlib`]),
|
||||||
in addition to emitting a C header file, which both can be linked
|
in addition to emitting a C header file, which both can be linked
|
||||||
against a sandboxed WebAssembly runtime environment for the
|
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
|
Made with ❤️ by the Wasmer team, for the community
|
||||||
|
|
||||||
[`wasmer-engine-universal`]: https://github.com/wasmerio/wasmer/tree/master/lib/engine-universal
|
[`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-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-singlepass`]: https://github.com/wasmerio/wasmer/tree/master/lib/compiler-singlepass
|
||||||
[`wasmer-compiler-cranelift`]: https://github.com/wasmerio/wasmer/tree/master/lib/compiler-cranelift
|
[`wasmer-compiler-cranelift`]: https://github.com/wasmerio/wasmer/tree/master/lib/compiler-cranelift
|
||||||
|
|||||||
@@ -77,8 +77,6 @@
|
|||||||
//! compilation process and to store the generated executable code
|
//! compilation process and to store the generated executable code
|
||||||
//! somewhere, either:
|
//! somewhere, either:
|
||||||
//! * in-memory (with [`wasmer-engine-universal`]),
|
//! * 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 a native static object file (with [`wasmer-engine-staticlib`]),
|
||||||
//! in addition to emitting a C header file, which both can be linked
|
//! in addition to emitting a C header file, which both can be linked
|
||||||
//! against a sandboxed WebAssembly runtime environment for the
|
//! against a sandboxed WebAssembly runtime environment for the
|
||||||
@@ -324,11 +322,7 @@
|
|||||||
//! - `universal`
|
//! - `universal`
|
||||||
#![cfg_attr(feature = "universal", doc = "(enabled),")]
|
#![cfg_attr(feature = "universal", doc = "(enabled),")]
|
||||||
#![cfg_attr(not(feature = "universal"), doc = "(disabled),")]
|
#![cfg_attr(not(feature = "universal"), doc = "(disabled),")]
|
||||||
//! enables [the Universal engine][`wasmer-engine-universal`],
|
//! 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`].
|
|
||||||
//!
|
//!
|
||||||
//! The features that set defaults come in sets that are mutually exclusive.
|
//! The features that set defaults come in sets that are mutually exclusive.
|
||||||
//!
|
//!
|
||||||
@@ -350,11 +344,7 @@
|
|||||||
//! - `default-universal`
|
//! - `default-universal`
|
||||||
#![cfg_attr(feature = "default-universal", doc = "(enabled),")]
|
#![cfg_attr(feature = "default-universal", doc = "(enabled),")]
|
||||||
#![cfg_attr(not(feature = "default-universal"), doc = "(disabled),")]
|
#![cfg_attr(not(feature = "default-universal"), doc = "(disabled),")]
|
||||||
//! set the Universal engine as the default,
|
//! 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.
|
|
||||||
//!
|
//!
|
||||||
#![cfg_attr(
|
#![cfg_attr(
|
||||||
feature = "js",
|
feature = "js",
|
||||||
@@ -434,7 +424,6 @@
|
|||||||
//! [`wasmer-emscripten`]: https://docs.rs/wasmer-emscripten/
|
//! [`wasmer-emscripten`]: https://docs.rs/wasmer-emscripten/
|
||||||
//! [wasmer-engine]: https://docs.rs/wasmer-engine/
|
//! [wasmer-engine]: https://docs.rs/wasmer-engine/
|
||||||
//! [`wasmer-engine-universal`]: https://docs.rs/wasmer-engine-universal/
|
//! [`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-engine-staticlib`]: https://docs.rs/wasmer-engine-staticlib/
|
||||||
//! [`wasmer-compiler-singlepass`]: https://docs.rs/wasmer-compiler-singlepass/
|
//! [`wasmer-compiler-singlepass`]: https://docs.rs/wasmer-compiler-singlepass/
|
||||||
//! [`wasmer-compiler-llvm`]: https://docs.rs/wasmer-compiler-llvm/
|
//! [`wasmer-compiler-llvm`]: https://docs.rs/wasmer-compiler-llvm/
|
||||||
|
|||||||
@@ -112,9 +112,6 @@ pub use wasmer_compiler_llvm::{LLVMOptLevel, LLVM};
|
|||||||
#[cfg(feature = "universal")]
|
#[cfg(feature = "universal")]
|
||||||
pub use wasmer_engine_universal::{Universal, UniversalArtifact, UniversalEngine};
|
pub use wasmer_engine_universal::{Universal, UniversalArtifact, UniversalEngine};
|
||||||
|
|
||||||
#[cfg(feature = "dylib")]
|
|
||||||
pub use wasmer_engine_dylib::{Dylib, DylibArtifact, DylibEngine};
|
|
||||||
|
|
||||||
/// Version number of this crate.
|
/// Version number of this crate.
|
||||||
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
|
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")]
|
#[deprecated(since = "2.0.0", note = "Please use the `universal` feature instead")]
|
||||||
pub type JIT = Universal;
|
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.
|
/// This type is deprecated, it has been replaced by TypedFunction.
|
||||||
#[deprecated(
|
#[deprecated(
|
||||||
since = "3.0.0",
|
since = "3.0.0",
|
||||||
|
|||||||
@@ -121,9 +121,6 @@ impl Default for Store {
|
|||||||
if #[cfg(feature = "default-universal")] {
|
if #[cfg(feature = "default-universal")] {
|
||||||
wasmer_engine_universal::Universal::new(config)
|
wasmer_engine_universal::Universal::new(config)
|
||||||
.engine()
|
.engine()
|
||||||
} else if #[cfg(feature = "default-dylib")] {
|
|
||||||
wasmer_engine_dylib::Dylib::new(config)
|
|
||||||
.engine()
|
|
||||||
} else {
|
} else {
|
||||||
compile_error!("No default engine chosen")
|
compile_error!("No default engine chosen")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ attributions of the project.
|
|||||||
|
|
||||||
|
|
||||||
[`wasmer-engine-universal`]: https://github.com/wasmerio/wasmer/tree/master/lib/engine-universal
|
[`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-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
|
[`wasmer-engine-dummy`]: https://github.com/wasmerio/wasmer/tree/master/tests/lib/engine-dummy
|
||||||
[`wasmtime-api`]: https://crates.io/crates/wasmtime
|
[`wasmtime-api`]: https://crates.io/crates/wasmtime
|
||||||
|
|||||||
@@ -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-emscripten = { version = "=2.3.0", path = "../emscripten", optional = true }
|
||||||
wasmer-engine = { version = "=2.3.0", path = "../engine" }
|
wasmer-engine = { version = "=2.3.0", path = "../engine" }
|
||||||
wasmer-engine-universal = { version = "=2.3.0", path = "../engine-universal", optional = true }
|
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-engine-staticlib = { version = "=2.3.0", path = "../engine-staticlib", optional = true }
|
||||||
wasmer-middlewares = { version = "=2.3.0", path = "../middlewares", 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 }
|
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",
|
"wasmer-engine-universal",
|
||||||
"engine",
|
"engine",
|
||||||
]
|
]
|
||||||
dylib = [
|
|
||||||
"wasmer-engine-dylib",
|
|
||||||
"engine",
|
|
||||||
]
|
|
||||||
staticlib = [
|
staticlib = [
|
||||||
"wasmer-engine-staticlib",
|
"wasmer-engine-staticlib",
|
||||||
"engine",
|
"engine",
|
||||||
@@ -77,7 +72,6 @@ staticlib = [
|
|||||||
compiler = [
|
compiler = [
|
||||||
"wasmer-api/compiler",
|
"wasmer-api/compiler",
|
||||||
"wasmer-engine-universal/compiler",
|
"wasmer-engine-universal/compiler",
|
||||||
"wasmer-engine-dylib/compiler",
|
|
||||||
"wasmer-engine-staticlib/compiler"
|
"wasmer-engine-staticlib/compiler"
|
||||||
]
|
]
|
||||||
singlepass = [
|
singlepass = [
|
||||||
@@ -95,7 +89,6 @@ llvm = [
|
|||||||
|
|
||||||
# Deprecated features.
|
# Deprecated features.
|
||||||
jit = ["universal"]
|
jit = ["universal"]
|
||||||
native = ["dylib"]
|
|
||||||
|
|
||||||
# TODO: Port this feature.
|
# TODO: Port this feature.
|
||||||
#emscripten = ["wasmer-emscripten"]
|
#emscripten = ["wasmer-emscripten"]
|
||||||
|
|||||||
@@ -13,8 +13,6 @@ use crate::error::update_last_error;
|
|||||||
use cfg_if::cfg_if;
|
use cfg_if::cfg_if;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use wasmer_api::Engine;
|
use wasmer_api::Engine;
|
||||||
#[cfg(feature = "dylib")]
|
|
||||||
use wasmer_engine_dylib::Dylib;
|
|
||||||
#[cfg(feature = "staticlib")]
|
#[cfg(feature = "staticlib")]
|
||||||
use wasmer_engine_staticlib::Staticlib;
|
use wasmer_engine_staticlib::Staticlib;
|
||||||
#[cfg(feature = "universal")]
|
#[cfg(feature = "universal")]
|
||||||
@@ -70,10 +68,6 @@ pub enum wasmer_engine_t {
|
|||||||
/// [`wasmer_engine_universal`] Rust crate.
|
/// [`wasmer_engine_universal`] Rust crate.
|
||||||
UNIVERSAL = 0,
|
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
|
/// Variant to represent the Staticlib engine. See the
|
||||||
/// [`wasmer_engine_staticlib`] Rust crate.
|
/// [`wasmer_engine_staticlib`] Rust crate.
|
||||||
STATICLIB = 2,
|
STATICLIB = 2,
|
||||||
@@ -84,8 +78,6 @@ impl Default for wasmer_engine_t {
|
|||||||
cfg_if! {
|
cfg_if! {
|
||||||
if #[cfg(feature = "universal")] {
|
if #[cfg(feature = "universal")] {
|
||||||
Self::UNIVERSAL
|
Self::UNIVERSAL
|
||||||
} else if #[cfg(feature = "dylib")] {
|
|
||||||
Self::DYLIB
|
|
||||||
} else if #[cfg(feature = "staticlib")] {
|
} else if #[cfg(feature = "staticlib")] {
|
||||||
Self::STATICLIB
|
Self::STATICLIB
|
||||||
} else {
|
} else {
|
||||||
@@ -251,10 +243,6 @@ pub extern "C" fn wasm_config_set_compiler(
|
|||||||
/// if (wasmer_is_engine_available(UNIVERSAL)) {
|
/// if (wasmer_is_engine_available(UNIVERSAL)) {
|
||||||
/// wasm_config_set_engine(config, 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.
|
/// // OK, let's do not specify any particular engine.
|
||||||
///
|
///
|
||||||
/// // Create the engine.
|
/// // Create the engine.
|
||||||
@@ -332,33 +320,6 @@ cfg_if! {
|
|||||||
let engine: Arc<dyn Engine + Send + Sync> = Arc::new(Universal::headless().engine());
|
let engine: Arc<dyn Engine + Send + Sync> = Arc::new(Universal::headless().engine());
|
||||||
Box::new(wasm_engine_t { inner: 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.
|
// 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.
|
// 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 => {
|
wasmer_engine_t::STATICLIB => {
|
||||||
cfg_if! {
|
cfg_if! {
|
||||||
// There are currently no uses of the Staticlib engine + compiler from the C API.
|
// 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 => {
|
wasmer_engine_t::STATICLIB => {
|
||||||
cfg_if! {
|
cfg_if! {
|
||||||
if #[cfg(feature = "staticlib")] {
|
if #[cfg(feature = "staticlib")] {
|
||||||
|
|||||||
@@ -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 {
|
pub extern "C" fn wasmer_is_engine_available(engine: wasmer_engine_t) -> bool {
|
||||||
match engine {
|
match engine {
|
||||||
wasmer_engine_t::UNIVERSAL if cfg!(feature = "universal") => true,
|
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,
|
wasmer_engine_t::STATICLIB if cfg!(feature = "staticlib") => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
@@ -245,7 +244,6 @@ mod tests {
|
|||||||
"0"
|
"0"
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
set_var("DYLIB", if cfg!(feature = "dylib") { "1" } else { "0" });
|
|
||||||
set_var(
|
set_var(
|
||||||
"STATICLIB",
|
"STATICLIB",
|
||||||
if cfg!(feature = "staticlib") {
|
if cfg!(feature = "staticlib") {
|
||||||
@@ -261,7 +259,6 @@ mod tests {
|
|||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
assert(wasmer_is_engine_available(UNIVERSAL) == (getenv("UNIVERSAL")[0] == '1'));
|
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'));
|
assert(wasmer_is_engine_available(STATICLIB) == (getenv("STATICLIB")[0] == '1'));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -270,7 +267,6 @@ mod tests {
|
|||||||
.success();
|
.success();
|
||||||
|
|
||||||
remove_var("UNIVERSAL");
|
remove_var("UNIVERSAL");
|
||||||
remove_var("DYLIB");
|
|
||||||
remove_var("STATICLIB");
|
remove_var("STATICLIB");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,9 +34,6 @@ wasm_engine_t *wasm_engine_new() {
|
|||||||
if (strcmp(wasmer_test_engine, "universal") == 0) {
|
if (strcmp(wasmer_test_engine, "universal") == 0) {
|
||||||
assert(wasmer_is_engine_available(UNIVERSAL));
|
assert(wasmer_is_engine_available(UNIVERSAL));
|
||||||
wasm_config_set_engine(config, 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) {
|
} else if (wasmer_test_engine) {
|
||||||
printf("Engine %s not recognized\n", wasmer_test_engine);
|
printf("Engine %s not recognized\n", wasmer_test_engine);
|
||||||
abort();
|
abort();
|
||||||
|
|||||||
1
lib/cache/Cargo.toml
vendored
1
lib/cache/Cargo.toml
vendored
@@ -22,7 +22,6 @@ tempfile = "3"
|
|||||||
rand = "0.8.3"
|
rand = "0.8.3"
|
||||||
wasmer-compiler-singlepass = { path = "../compiler-singlepass", version = "=2.3.0" }
|
wasmer-compiler-singlepass = { path = "../compiler-singlepass", version = "=2.3.0" }
|
||||||
wasmer-engine-universal = { path = "../engine-universal", 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]
|
[features]
|
||||||
default = ["wasmer/js-serializable-module", "filesystem"]
|
default = ["wasmer/js-serializable-module", "filesystem"]
|
||||||
|
|||||||
1
lib/cache/benches/bench_filesystem_cache.rs
vendored
1
lib/cache/benches/bench_filesystem_cache.rs
vendored
@@ -7,7 +7,6 @@ use wasmer::{Module, Store};
|
|||||||
use wasmer_cache::Cache;
|
use wasmer_cache::Cache;
|
||||||
use wasmer_cache::{FileSystemCache, Hash};
|
use wasmer_cache::{FileSystemCache, Hash};
|
||||||
use wasmer_compiler_singlepass::Singlepass;
|
use wasmer_compiler_singlepass::Singlepass;
|
||||||
use wasmer_engine_dylib::Dylib;
|
|
||||||
use wasmer_engine_universal::Universal;
|
use wasmer_engine_universal::Universal;
|
||||||
|
|
||||||
fn random_key() -> Hash {
|
fn random_key() -> Hash {
|
||||||
|
|||||||
@@ -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-emscripten = { version = "=2.3.0", path = "../emscripten", optional = true }
|
||||||
wasmer-engine = { version = "=2.3.0", path = "../engine" }
|
wasmer-engine = { version = "=2.3.0", path = "../engine" }
|
||||||
wasmer-engine-universal = { version = "=2.3.0", path = "../engine-universal", optional = true }
|
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-engine-staticlib = { version = "=2.3.0", path = "../engine-staticlib", optional = true }
|
||||||
wasmer-vm = { version = "=2.3.0", path = "../vm" }
|
wasmer-vm = { version = "=2.3.0", path = "../vm" }
|
||||||
wasmer-wasi = { version = "=2.3.0", path = "../wasi", optional = true }
|
wasmer-wasi = { version = "=2.3.0", path = "../wasi", optional = true }
|
||||||
@@ -66,7 +65,6 @@ default = [
|
|||||||
"wat",
|
"wat",
|
||||||
"wast",
|
"wast",
|
||||||
"universal",
|
"universal",
|
||||||
"dylib",
|
|
||||||
"staticlib",
|
"staticlib",
|
||||||
"cache",
|
"cache",
|
||||||
"wasi",
|
"wasi",
|
||||||
@@ -77,10 +75,6 @@ universal = [
|
|||||||
"wasmer-engine-universal",
|
"wasmer-engine-universal",
|
||||||
"engine",
|
"engine",
|
||||||
]
|
]
|
||||||
dylib = [
|
|
||||||
"wasmer-engine-dylib",
|
|
||||||
"engine",
|
|
||||||
]
|
|
||||||
staticlib = [
|
staticlib = [
|
||||||
"wasmer-engine-staticlib",
|
"wasmer-engine-staticlib",
|
||||||
"engine",
|
"engine",
|
||||||
@@ -94,7 +88,6 @@ wat = ["wasmer/wat"]
|
|||||||
compiler = [
|
compiler = [
|
||||||
"wasmer-compiler/translator",
|
"wasmer-compiler/translator",
|
||||||
"wasmer-engine-universal/compiler",
|
"wasmer-engine-universal/compiler",
|
||||||
"wasmer-engine-dylib/compiler",
|
|
||||||
"wasmer-engine-staticlib/compiler",
|
"wasmer-engine-staticlib/compiler",
|
||||||
]
|
]
|
||||||
experimental-io-devices = [
|
experimental-io-devices = [
|
||||||
@@ -116,8 +109,7 @@ llvm = [
|
|||||||
debug = ["fern", "log", "wasmer-wasi/logging"]
|
debug = ["fern", "log", "wasmer-wasi/logging"]
|
||||||
disable-all-logging = ["wasmer-wasi/disable-all-logging"]
|
disable-all-logging = ["wasmer-wasi/disable-all-logging"]
|
||||||
headless = []
|
headless = []
|
||||||
headless-minimal = ["headless", "disable-all-logging", "wasi", "dylib", "universal"]
|
headless-minimal = ["headless", "disable-all-logging", "wasi", "universal"]
|
||||||
|
|
||||||
# Deprecated features.
|
# Deprecated features.
|
||||||
jit = ["universal"]
|
jit = ["universal"]
|
||||||
native = ["dylib"]
|
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ The Wasmer supports the following features:
|
|||||||
* `wat` (default): support for executing WebAssembly text files.
|
* `wat` (default): support for executing WebAssembly text files.
|
||||||
* `wast`(default): support for running wast test files.
|
* `wast`(default): support for running wast test files.
|
||||||
* `universal` (default): support for the [Universal engine].
|
* `universal` (default): support for the [Universal engine].
|
||||||
* `dylib` (default): support for the [Dylib engine].
|
|
||||||
* `cache` (default): support or automatically caching compiled artifacts.
|
* `cache` (default): support or automatically caching compiled artifacts.
|
||||||
* `wasi` (default): support for [WASI].
|
* `wasi` (default): support for [WASI].
|
||||||
* `experimental-io-devices`: support for experimental IO devices in 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].
|
* `llvm`: support for the [LLVM compiler].
|
||||||
|
|
||||||
[Universal engine]: https://github.com/wasmerio/wasmer/tree/master/lib/engine-universal/
|
[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/
|
[WASI]: https://github.com/wasmerio/wasmer/tree/master/lib/wasi/
|
||||||
[Emscripten]: https://github.com/wasmerio/wasmer/tree/master/lib/emscripten/
|
[Emscripten]: https://github.com/wasmerio/wasmer/tree/master/lib/emscripten/
|
||||||
[Singlepass compiler]: https://github.com/wasmerio/wasmer/tree/master/lib/compiler-singlepass/
|
[Singlepass compiler]: https://github.com/wasmerio/wasmer/tree/master/lib/compiler-singlepass/
|
||||||
@@ -62,11 +60,11 @@ wasmer run myfile.wasm
|
|||||||
Compile a WebAssembly file:
|
Compile a WebAssembly file:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
wasmer compile myfile.wasm -o myfile.so --dylib
|
wasmer compile myfile.wasm -o myfile.wasmu --universal
|
||||||
```
|
```
|
||||||
|
|
||||||
Run a compiled WebAssembly file (fastest):
|
Run a compiled WebAssembly file (fastest):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
wasmer run myfile.so
|
wasmer run myfile.wasmu
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -43,10 +43,6 @@ impl Compile {
|
|||||||
target_triple: &Triple,
|
target_triple: &Triple,
|
||||||
) -> Result<&'static str> {
|
) -> Result<&'static str> {
|
||||||
Ok(match engine_type {
|
Ok(match engine_type {
|
||||||
#[cfg(feature = "dylib")]
|
|
||||||
EngineType::Dylib => {
|
|
||||||
wasmer_engine_dylib::DylibArtifact::get_default_extension(target_triple)
|
|
||||||
}
|
|
||||||
#[cfg(feature = "universal")]
|
#[cfg(feature = "universal")]
|
||||||
EngineType::Universal => {
|
EngineType::Universal => {
|
||||||
wasmer_engine_universal::UniversalArtifact::get_default_extension(target_triple)
|
wasmer_engine_universal::UniversalArtifact::get_default_extension(target_triple)
|
||||||
@@ -55,7 +51,7 @@ impl Compile {
|
|||||||
EngineType::Staticlib => {
|
EngineType::Staticlib => {
|
||||||
wasmer_engine_staticlib::StaticlibArtifact::get_default_extension(target_triple)
|
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"),
|
_ => bail!("selected engine type is not compiled in"),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -223,15 +223,6 @@ impl Run {
|
|||||||
|
|
||||||
fn get_module(&self) -> Result<Module> {
|
fn get_module(&self) -> Result<Module> {
|
||||||
let contents = std::fs::read(self.path.clone())?;
|
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")]
|
#[cfg(feature = "universal")]
|
||||||
{
|
{
|
||||||
if wasmer_engine_universal::UniversalArtifact::is_deserializable(&contents) {
|
if wasmer_engine_universal::UniversalArtifact::is_deserializable(&contents) {
|
||||||
@@ -314,16 +305,8 @@ impl Run {
|
|||||||
cache_dir_root.push(compiler_type.to_string());
|
cache_dir_root.push(compiler_type.to_string());
|
||||||
let mut cache = FileSystemCache::new(cache_dir_root)?;
|
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)]
|
#[allow(unreachable_patterns)]
|
||||||
let extension = match *engine_type {
|
let extension = match *engine_type {
|
||||||
#[cfg(feature = "dylib")]
|
|
||||||
EngineType::Dylib => {
|
|
||||||
wasmer_engine_dylib::DylibArtifact::get_default_extension(&Triple::host())
|
|
||||||
.to_string()
|
|
||||||
}
|
|
||||||
#[cfg(feature = "universal")]
|
#[cfg(feature = "universal")]
|
||||||
EngineType::Universal => {
|
EngineType::Universal => {
|
||||||
wasmer_engine_universal::UniversalArtifact::get_default_extension(&Triple::host())
|
wasmer_engine_universal::UniversalArtifact::get_default_extension(&Triple::host())
|
||||||
|
|||||||
@@ -23,27 +23,19 @@ pub struct StoreOptions {
|
|||||||
compiler: CompilerOptions,
|
compiler: CompilerOptions,
|
||||||
|
|
||||||
/// Use the Universal Engine.
|
/// 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,
|
universal: bool,
|
||||||
|
|
||||||
/// Use the Dylib Engine.
|
|
||||||
#[structopt(long, conflicts_with_all = &["universal", "staticlib", "jit", "native", "object_file"])]
|
|
||||||
dylib: bool,
|
|
||||||
|
|
||||||
/// Use the Staticlib Engine.
|
/// 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,
|
staticlib: bool,
|
||||||
|
|
||||||
/// Use the JIT (Universal) Engine.
|
/// 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,
|
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.
|
/// 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,
|
object_file: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,13 +142,6 @@ impl CompilerOptions {
|
|||||||
.target(target)
|
.target(target)
|
||||||
.engine(),
|
.engine(),
|
||||||
),
|
),
|
||||||
#[cfg(feature = "dylib")]
|
|
||||||
EngineType::Dylib => Box::new(
|
|
||||||
wasmer_engine_dylib::Dylib::new(compiler_config)
|
|
||||||
.target(target)
|
|
||||||
.features(features)
|
|
||||||
.engine(),
|
|
||||||
),
|
|
||||||
#[cfg(feature = "staticlib")]
|
#[cfg(feature = "staticlib")]
|
||||||
EngineType::Staticlib => Box::new(
|
EngineType::Staticlib => Box::new(
|
||||||
wasmer_engine_staticlib::Staticlib::new(compiler_config)
|
wasmer_engine_staticlib::Staticlib::new(compiler_config)
|
||||||
@@ -164,7 +149,7 @@ impl CompilerOptions {
|
|||||||
.features(features)
|
.features(features)
|
||||||
.engine(),
|
.engine(),
|
||||||
),
|
),
|
||||||
#[cfg(not(all(feature = "universal", feature = "dylib", feature = "staticlib")))]
|
#[cfg(not(all(feature = "universal", feature = "staticlib")))]
|
||||||
engine => bail!(
|
engine => bail!(
|
||||||
"The `{}` engine is not included in this binary.",
|
"The `{}` engine is not included in this binary.",
|
||||||
engine.to_string()
|
engine.to_string()
|
||||||
@@ -356,8 +341,6 @@ impl ToString for CompilerType {
|
|||||||
pub enum EngineType {
|
pub enum EngineType {
|
||||||
/// Universal Engine
|
/// Universal Engine
|
||||||
Universal,
|
Universal,
|
||||||
/// Dylib Engine
|
|
||||||
Dylib,
|
|
||||||
/// Static Engine
|
/// Static Engine
|
||||||
Staticlib,
|
Staticlib,
|
||||||
}
|
}
|
||||||
@@ -366,7 +349,6 @@ impl ToString for EngineType {
|
|||||||
fn to_string(&self) -> String {
|
fn to_string(&self) -> String {
|
||||||
match self {
|
match self {
|
||||||
Self::Universal => "universal".to_string(),
|
Self::Universal => "universal".to_string(),
|
||||||
Self::Dylib => "dylib".to_string(),
|
|
||||||
Self::Staticlib => "staticlib".to_string(),
|
Self::Staticlib => "staticlib".to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -410,16 +392,12 @@ impl StoreOptions {
|
|||||||
fn get_engine(&self) -> Result<EngineType> {
|
fn get_engine(&self) -> Result<EngineType> {
|
||||||
if self.universal || self.jit {
|
if self.universal || self.jit {
|
||||||
Ok(EngineType::Universal)
|
Ok(EngineType::Universal)
|
||||||
} else if self.dylib || self.native {
|
|
||||||
Ok(EngineType::Dylib)
|
|
||||||
} else if self.staticlib || self.object_file {
|
} else if self.staticlib || self.object_file {
|
||||||
Ok(EngineType::Staticlib)
|
Ok(EngineType::Staticlib)
|
||||||
} else {
|
} else {
|
||||||
// Auto mode, we choose the best engine for that platform
|
// Auto mode, we choose the best engine for that platform
|
||||||
if cfg!(feature = "universal") {
|
if cfg!(feature = "universal") {
|
||||||
Ok(EngineType::Universal)
|
Ok(EngineType::Universal)
|
||||||
} else if cfg!(feature = "dylib") {
|
|
||||||
Ok(EngineType::Dylib)
|
|
||||||
} else if cfg!(feature = "staticlib") {
|
} else if cfg!(feature = "staticlib") {
|
||||||
Ok(EngineType::Staticlib)
|
Ok(EngineType::Staticlib)
|
||||||
} else {
|
} else {
|
||||||
@@ -439,13 +417,11 @@ impl StoreOptions {
|
|||||||
EngineType::Universal => {
|
EngineType::Universal => {
|
||||||
Arc::new(wasmer_engine_universal::Universal::headless().engine())
|
Arc::new(wasmer_engine_universal::Universal::headless().engine())
|
||||||
}
|
}
|
||||||
#[cfg(feature = "dylib")]
|
|
||||||
EngineType::Dylib => Arc::new(wasmer_engine_dylib::Dylib::headless().engine()),
|
|
||||||
#[cfg(feature = "staticlib")]
|
#[cfg(feature = "staticlib")]
|
||||||
EngineType::Staticlib => {
|
EngineType::Staticlib => {
|
||||||
Arc::new(wasmer_engine_staticlib::Staticlib::headless().engine())
|
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!(
|
engine => bail!(
|
||||||
"The `{}` engine is not included in this binary.",
|
"The `{}` engine is not included in this binary.",
|
||||||
engine.to_string()
|
engine.to_string()
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ impl Cranelift {
|
|||||||
flags.enable("is_pic").expect("should be a valid flag");
|
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.
|
// These trampolines are always reachable through short jumps.
|
||||||
flags
|
flags
|
||||||
.enable("use_colocated_libcalls")
|
.enable("use_colocated_libcalls")
|
||||||
|
|||||||
@@ -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" }
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
# `wasmer-engine-dylib` [](https://github.com/wasmerio/wasmer/actions?query=workflow%3Abuild) [](https://slack.wasmer.io) [](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
|
|
||||||
@@ -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(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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");
|
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -5,14 +5,13 @@ This crate is the general abstraction for creating Engines in Wasmer.
|
|||||||
Wasmer Engines are mainly responsible for two things:
|
Wasmer Engines are mainly responsible for two things:
|
||||||
* Transform the compilation code (from any Wasmer Compiler) to
|
* Transform the compilation code (from any Wasmer Compiler) to
|
||||||
**create** an `Artifact`,
|
**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).
|
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`],
|
1. Universal with [`wasmer-engine-universal`],
|
||||||
2. Native with [`wasmer-engine-dylib`],
|
2. Object with [`wasmer-engine-staticlib`].
|
||||||
3. Object with [`wasmer-engine-staticlib`].
|
|
||||||
|
|
||||||
## Example Implementation
|
## 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-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-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
|
[`wasmer-engine-dummy`]: https://github.com/wasmerio/wasmer/tree/master/tests/lib/engine-dummy
|
||||||
[`wasmtime-api`]: https://crates.io/crates/wasmtime
|
[`wasmtime-api`]: https://crates.io/crates/wasmtime
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ attributions of the project.
|
|||||||
|
|
||||||
|
|
||||||
[`wasmer-engine-universal`]: https://github.com/wasmerio/wasmer/tree/master/lib/engine-universal
|
[`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-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
|
[`wasmer-engine-dummy`]: https://github.com/wasmerio/wasmer/tree/master/tests/lib/engine-dummy
|
||||||
[`wasmtime-api`]: https://crates.io/crates/wasmtime
|
[`wasmtime-api`]: https://crates.io/crates/wasmtime
|
||||||
|
|||||||
@@ -59,16 +59,6 @@ dep_graph = {
|
|||||||
"wasmer-engine",
|
"wasmer-engine",
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
"wasmer-engine-dylib": set(
|
|
||||||
[
|
|
||||||
"wasmer-artifact",
|
|
||||||
"wasmer-types",
|
|
||||||
"wasmer-compiler",
|
|
||||||
"wasmer-vm",
|
|
||||||
"wasmer-engine",
|
|
||||||
"wasmer-object",
|
|
||||||
]
|
|
||||||
),
|
|
||||||
"wasmer-engine-staticlib": set(
|
"wasmer-engine-staticlib": set(
|
||||||
[
|
[
|
||||||
"wasmer-artifact",
|
"wasmer-artifact",
|
||||||
@@ -91,7 +81,6 @@ dep_graph = {
|
|||||||
"wasmer-compiler-cranelift",
|
"wasmer-compiler-cranelift",
|
||||||
"wasmer-compiler-llvm",
|
"wasmer-compiler-llvm",
|
||||||
"wasmer-engine-universal",
|
"wasmer-engine-universal",
|
||||||
"wasmer-engine-dylib",
|
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
"wasmer-vfs": set([]),
|
"wasmer-vfs": set([]),
|
||||||
@@ -110,7 +99,6 @@ dep_graph = {
|
|||||||
"wasmer-emscripten",
|
"wasmer-emscripten",
|
||||||
"wasmer-engine",
|
"wasmer-engine",
|
||||||
"wasmer-engine-universal",
|
"wasmer-engine-universal",
|
||||||
"wasmer-engine-dylib",
|
|
||||||
"wasmer-engine-staticlib",
|
"wasmer-engine-staticlib",
|
||||||
"wasmer-middlewares",
|
"wasmer-middlewares",
|
||||||
"wasmer-wasi",
|
"wasmer-wasi",
|
||||||
@@ -129,7 +117,6 @@ dep_graph = {
|
|||||||
"wasmer-emscripten",
|
"wasmer-emscripten",
|
||||||
"wasmer-engine",
|
"wasmer-engine",
|
||||||
"wasmer-engine-universal",
|
"wasmer-engine-universal",
|
||||||
"wasmer-engine-dylib",
|
|
||||||
"wasmer-engine-staticlib",
|
"wasmer-engine-staticlib",
|
||||||
"wasmer-vm",
|
"wasmer-vm",
|
||||||
"wasmer-wasi",
|
"wasmer-wasi",
|
||||||
@@ -159,7 +146,6 @@ location = {
|
|||||||
"wasmer-compiler-llvm": "compiler-llvm",
|
"wasmer-compiler-llvm": "compiler-llvm",
|
||||||
"wasmer-engine": "engine",
|
"wasmer-engine": "engine",
|
||||||
"wasmer-engine-universal": "engine-universal",
|
"wasmer-engine-universal": "engine-universal",
|
||||||
"wasmer-engine-dylib": "engine-dylib",
|
|
||||||
"wasmer-engine-staticlib": "engine-staticlib",
|
"wasmer-engine-staticlib": "engine-staticlib",
|
||||||
"wasmer-cache": "cache",
|
"wasmer-cache": "cache",
|
||||||
"wasmer": "api",
|
"wasmer": "api",
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ pub enum Compiler {
|
|||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum Engine {
|
pub enum Engine {
|
||||||
Dylib,
|
|
||||||
Universal,
|
Universal,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,14 +60,6 @@ impl Config {
|
|||||||
#[cfg(not(feature = "engine"))]
|
#[cfg(not(feature = "engine"))]
|
||||||
compile_error!("Plese enable at least one engine via the features");
|
compile_error!("Plese enable at least one engine via the features");
|
||||||
match &self.engine {
|
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")]
|
#[cfg(feature = "universal")]
|
||||||
Engine::Universal => {
|
Engine::Universal => {
|
||||||
let mut engine = wasmer_engine_universal::Universal::new(compiler_config);
|
let mut engine = wasmer_engine_universal::Universal::new(compiler_config);
|
||||||
@@ -87,8 +78,6 @@ impl Config {
|
|||||||
|
|
||||||
pub fn engine_headless(&self) -> Box<dyn WasmerEngine> {
|
pub fn engine_headless(&self) -> Box<dyn WasmerEngine> {
|
||||||
match &self.engine {
|
match &self.engine {
|
||||||
#[cfg(feature = "dylib")]
|
|
||||||
Engine::Dylib => Box::new(wasmer_engine_dylib::Dylib::headless().engine()),
|
|
||||||
#[cfg(feature = "universal")]
|
#[cfg(feature = "universal")]
|
||||||
Engine::Universal => Box::new(wasmer_engine_universal::Universal::headless().engine()),
|
Engine::Universal => Box::new(wasmer_engine_universal::Universal::headless().engine()),
|
||||||
#[allow(unreachable_patterns)]
|
#[allow(unreachable_patterns)]
|
||||||
|
|||||||
@@ -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");
|
wast.allow_trap_message("uninitialized element 2", "uninitialized element");
|
||||||
// `liking.wast` has different wording but the same meaning
|
// `liking.wast` has different wording but the same meaning
|
||||||
wast.allow_trap_message("out of bounds memory access", "memory out of bounds");
|
wast.allow_trap_message("out of bounds memory access", "memory out of bounds");
|
||||||
|
/*
|
||||||
if config.compiler == crate::Compiler::Cranelift && config.engine == crate::Engine::Dylib {
|
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("call stack exhausted", "out of bounds memory access");
|
||||||
wast.allow_trap_message("indirect call type mismatch", "call stack exhausted");
|
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("uninitialized element", "call stack exhausted");
|
||||||
wast.allow_trap_message("unreachable", "call stack exhausted");
|
wast.allow_trap_message("unreachable", "call stack exhausted");
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
if cfg!(feature = "coverage") {
|
if cfg!(feature = "coverage") {
|
||||||
wast.disable_assert_and_exhaustion();
|
wast.disable_assert_and_exhaustion();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,37 +2,27 @@
|
|||||||
singlepass spec::multi_value # Singlepass has not implemented multivalue (functions that returns "structs"/"tuples")
|
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)
|
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
|
||||||
## Traps. Tracing doesn't work properly in Singlepass
|
## Traps. Tracing doesn't work properly in Singlepass
|
||||||
## Unwinding is not properly implemented in Singlepass
|
## Unwinding is not properly implemented in Singlepass
|
||||||
# Needs investigation
|
# Needs investigation
|
||||||
singlepass+aarch64+macos traps::test_trap_trace
|
singlepass+aarch64+macos traps::test_trap_trace
|
||||||
dylib traps::test_trap_trace
|
|
||||||
cranelift+aarch64 traps::test_trap_trace
|
cranelift+aarch64 traps::test_trap_trace
|
||||||
singlepass+aarch64+macos traps::test_trap_stack_overflow # Need to investigate
|
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
|
cranelift+aarch64 traps::test_trap_stack_overflow # Need to investigate
|
||||||
singlepass+aarch64+macos traps::trap_display_pretty
|
singlepass+aarch64+macos traps::trap_display_pretty
|
||||||
llvm traps::trap_display_pretty
|
llvm traps::trap_display_pretty
|
||||||
dylib traps::trap_display_pretty
|
|
||||||
cranelift+aarch64 traps::trap_display_pretty
|
cranelift+aarch64 traps::trap_display_pretty
|
||||||
singlepass+aarch64+macos traps::trap_display_multi_module
|
singlepass+aarch64+macos traps::trap_display_multi_module
|
||||||
llvm traps::trap_display_multi_module
|
llvm traps::trap_display_multi_module
|
||||||
dylib traps::trap_display_multi_module
|
|
||||||
cranelift+aarch64 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
|
singlepass traps::call_signature_mismatch # Need to investigate, get foo (a[0]:0x33) instead of 0x30 for inderect call
|
||||||
llvm traps::call_signature_mismatch
|
llvm traps::call_signature_mismatch
|
||||||
dylib traps::call_signature_mismatch
|
|
||||||
macos+aarch64 traps::call_signature_mismatch
|
macos+aarch64 traps::call_signature_mismatch
|
||||||
singlepass+aarch64+macos traps::start_trap_pretty
|
singlepass+aarch64+macos traps::start_trap_pretty
|
||||||
llvm traps::start_trap_pretty
|
llvm traps::start_trap_pretty
|
||||||
dylib traps::start_trap_pretty
|
|
||||||
cranelift+aarch64 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
|
singlepass multi_value_imports::dynamic # Singlepass doesn't support multivalue
|
||||||
|
|
||||||
# Also neither LLVM nor Cranelift currently implement stack probing on AArch64.
|
# Also neither LLVM nor Cranelift currently implement stack probing on AArch64.
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ impl Compiler {
|
|||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub enum Engine {
|
pub enum Engine {
|
||||||
Universal,
|
Universal,
|
||||||
Dylib,
|
|
||||||
Staticlib,
|
Staticlib,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,7 +29,6 @@ impl Engine {
|
|||||||
pub const fn to_flag(self) -> &'static str {
|
pub const fn to_flag(self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
Engine::Universal => "--universal",
|
Engine::Universal => "--universal",
|
||||||
Engine::Dylib => "--dylib",
|
|
||||||
Engine::Staticlib => "--staticlib",
|
Engine::Staticlib => "--staticlib",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ impl Ignores {
|
|||||||
arch = Some(alias.to_string());
|
arch = Some(alias.to_string());
|
||||||
}
|
}
|
||||||
// Engines
|
// Engines
|
||||||
"universal" | "dylib" => {
|
"universal" => {
|
||||||
engine = Some(alias.to_string());
|
engine = Some(alias.to_string());
|
||||||
}
|
}
|
||||||
// Compilers
|
// Compilers
|
||||||
|
|||||||
@@ -112,7 +112,6 @@ pub fn compiler_test(attrs: TokenStream, input: TokenStream) -> TokenStream {
|
|||||||
let mod_name = ::quote::format_ident!("{}", compiler_name.to_lowercase());
|
let mod_name = ::quote::format_ident!("{}", compiler_name.to_lowercase());
|
||||||
let universal_engine_test =
|
let universal_engine_test =
|
||||||
construct_engine_test(func, compiler_name, "Universal", "universal");
|
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();
|
let compiler_name_lowercase = compiler_name.to_lowercase();
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
@@ -121,7 +120,6 @@ pub fn compiler_test(attrs: TokenStream, input: TokenStream) -> TokenStream {
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#universal_engine_test
|
#universal_engine_test
|
||||||
#dylib_engine_test
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -63,15 +63,6 @@ gen_tests! {
|
|||||||
crate::Compiler::Singlepass
|
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")]
|
#[cfg(feature = "cranelift")]
|
||||||
@@ -86,15 +77,6 @@ gen_tests! {
|
|||||||
crate::Compiler::Cranelift
|
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")]
|
#[cfg(feature = "llvm")]
|
||||||
@@ -109,15 +91,6 @@ gen_tests! {
|
|||||||
crate::Compiler::LLVM
|
crate::Compiler::LLVM
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
#[test_log::test]
|
|
||||||
#[cold]
|
|
||||||
#[cfg(feature = "dylib")]
|
|
||||||
fn dylib() {
|
|
||||||
foo(crate::Config::new(
|
|
||||||
crate::Engine::Dylib,
|
|
||||||
crate::Compiler::LLVM
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,5 +10,4 @@ anyhow = "1.0"
|
|||||||
target-lexicon = "0.12"
|
target-lexicon = "0.12"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
test-dylib = []
|
|
||||||
test-universal = []
|
test-universal = []
|
||||||
|
|||||||
Reference in New Issue
Block a user