mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-08 13:48:26 +00:00
Merge branch 'master' into js-api-improvement
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
[target.'cfg(target_os = "linux")']
|
[target.'cfg(all(target_os = "linux", target_env = "gnu"))']
|
||||||
rustflags = [
|
rustflags = [
|
||||||
# Put the VM functions in the dynamic symbol table.
|
# Put the VM functions in the dynamic symbol table.
|
||||||
"-C", "link-arg=-Wl,-E",
|
"-C", "link-arg=-Wl,-E",
|
||||||
|
|||||||
10
.github/workflows/documentation.yaml
vendored
10
.github/workflows/documentation.yaml
vendored
@@ -22,14 +22,14 @@ jobs:
|
|||||||
- name: Install LLVM
|
- name: Install LLVM
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
curl --proto '=https' --tlsv1.2 -sSf ${{ env.LLVM_URL }} -L -o llvm.tar.gz
|
curl --proto '=https' --tlsv1.2 -sSf ${{ env.LLVM_URL }} -L -o llvm.tar.xz
|
||||||
mkdir ${{ env.LLVM_DIR }}
|
mkdir ${{ env.LLVM_DIR }}
|
||||||
tar xf llvm.tar.gz --strip-components=1 -C ${{ env.LLVM_DIR }}
|
tar xf llvm.tar.xz --strip-components=1 -C ${{ env.LLVM_DIR }}
|
||||||
echo "${{ env.LLVM_DIR }}/bin" >> $GITHUB_PATH
|
echo "${{ env.LLVM_DIR }}/bin" >> $GITHUB_PATH
|
||||||
echo "LLVM_SYS_110_PREFIX=${{ env.LLVM_DIR }}" >> $GITHUB_ENV
|
echo "LLVM_SYS_120_PREFIX=${{ env.LLVM_DIR }}" >> $GITHUB_ENV
|
||||||
env:
|
env:
|
||||||
LLVM_DIR: ${{ github.workspace }}/llvm-11
|
LLVM_DIR: ${{ github.workspace }}/llvm-13
|
||||||
LLVM_URL: 'https://github.com/wasmerio/llvm-custom-builds/releases/download/11.x/linux-amd64.tar.gz'
|
LLVM_URL: 'https://github.com/llvm/llvm-project/releases/download/llvmorg-13.0.0/clang+llvm-13.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz'
|
||||||
- name: Build & package documentation
|
- name: Build & package documentation
|
||||||
run: make package-docs
|
run: make package-docs
|
||||||
- name: Publish documentation
|
- name: Publish documentation
|
||||||
|
|||||||
10
.github/workflows/lint.yaml
vendored
10
.github/workflows/lint.yaml
vendored
@@ -23,11 +23,11 @@ jobs:
|
|||||||
components: rustfmt, clippy
|
components: rustfmt, clippy
|
||||||
- name: Install LLVM (Linux)
|
- name: Install LLVM (Linux)
|
||||||
run: |
|
run: |
|
||||||
curl --proto '=https' --tlsv1.2 -sSf https://github.com/wasmerio/llvm-custom-builds/releases/download/11.x/linux-amd64.tar.gz -L -o /opt/llvm.tar.gz
|
curl --proto '=https' --tlsv1.2 -sSf https://github.com/llvm/llvm-project/releases/download/llvmorg-13.0.0/clang+llvm-13.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz -L -o /opt/llvm.tar.xz
|
||||||
mkdir -p /opt/llvm-11
|
mkdir -p /opt/llvm-12
|
||||||
tar xf /opt/llvm.tar.gz --strip-components=1 -C /opt/llvm-11
|
tar xf /opt/llvm.tar.xz --strip-components=1 -C /opt/llvm-12
|
||||||
echo '/opt/llvm-11/bin' >> $GITHUB_PATH
|
echo '/opt/llvm-12/bin' >> $GITHUB_PATH
|
||||||
echo 'LLVM_SYS_110_PREFIX=/opt/llvm-11' >> $GITHUB_ENV
|
echo 'LLVM_SYS_120_PREFIX=/opt/llvm-12' >> $GITHUB_ENV
|
||||||
- run: make lint
|
- run: make lint
|
||||||
env:
|
env:
|
||||||
ENABLE_CRANELIFT: "1"
|
ENABLE_CRANELIFT: "1"
|
||||||
|
|||||||
18
.github/workflows/test-sys.yaml
vendored
18
.github/workflows/test-sys.yaml
vendored
@@ -42,7 +42,7 @@ jobs:
|
|||||||
include:
|
include:
|
||||||
- build: linux-x64
|
- build: linux-x64
|
||||||
os: ubuntu-18.04
|
os: ubuntu-18.04
|
||||||
llvm_url: 'https://github.com/wasmerio/llvm-custom-builds/releases/download/11.x/linux-amd64.tar.gz'
|
llvm_url: 'https://github.com/llvm/llvm-project/releases/download/llvmorg-13.0.0/clang+llvm-13.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz'
|
||||||
artifact_name: 'wasmer-linux-amd64'
|
artifact_name: 'wasmer-linux-amd64'
|
||||||
cross_compilation_artifact_name: 'cross_compiled_from_linux'
|
cross_compilation_artifact_name: 'cross_compiled_from_linux'
|
||||||
run_test: true
|
run_test: true
|
||||||
@@ -51,7 +51,7 @@ jobs:
|
|||||||
use_sccache: true
|
use_sccache: true
|
||||||
- build: macos-x64
|
- build: macos-x64
|
||||||
os: macos-11
|
os: macos-11
|
||||||
llvm_url: 'https://github.com/wasmerio/llvm-custom-builds/releases/download/11.x/darwin-amd64.tar.gz'
|
llvm_url: 'https://github.com/llvm/llvm-project/releases/download/llvmorg-13.0.0/clang+llvm-13.0.0-x86_64-apple-darwin.tar.xz'
|
||||||
artifact_name: 'wasmer-darwin-amd64'
|
artifact_name: 'wasmer-darwin-amd64'
|
||||||
cross_compilation_artifact_name: 'cross_compiled_from_mac'
|
cross_compilation_artifact_name: 'cross_compiled_from_mac'
|
||||||
run_test: true
|
run_test: true
|
||||||
@@ -68,8 +68,8 @@ jobs:
|
|||||||
run_test_capi: false
|
run_test_capi: false
|
||||||
- build: windows-x64
|
- build: windows-x64
|
||||||
os: windows-latest
|
os: windows-latest
|
||||||
# llvm_url: 'https://github.com/wasmerio/llvm-custom-builds/releases/download/11.x/windows-amd64.tar.gz'
|
# llvm_url: 'https://github.com/wasmerio/llvm-custom-builds/releases/download/12.x/windows-amd64.tar.gz'
|
||||||
llvm_choco_version: 12.0.1
|
llvm_choco_version: 13.0.0
|
||||||
artifact_name: 'wasmer-windows-amd64'
|
artifact_name: 'wasmer-windows-amd64'
|
||||||
cross_compilation_artifact_name: 'cross_compiled_from_win'
|
cross_compilation_artifact_name: 'cross_compiled_from_win'
|
||||||
run_integration_tests: true
|
run_integration_tests: true
|
||||||
@@ -80,7 +80,7 @@ jobs:
|
|||||||
# os: [self-hosted, linux, ARM64]
|
# os: [self-hosted, linux, ARM64]
|
||||||
# random_sccache_port: true
|
# random_sccache_port: true
|
||||||
# use_sccache: true
|
# use_sccache: true
|
||||||
# llvm_url: 'https://github.com/wasmerio/llvm-custom-builds/releases/download/11.x/linux-aarch64.tar.gz'
|
# llvm_url: 'https://github.com/wasmerio/llvm-custom-builds/releases/download/12.x/linux-aarch64.tar.gz'
|
||||||
# artifact_name: 'wasmer-linux-aarch64'
|
# artifact_name: 'wasmer-linux-aarch64'
|
||||||
# run_integration_tests: false
|
# run_integration_tests: false
|
||||||
- build: linux-musl-x64
|
- build: linux-musl-x64
|
||||||
@@ -122,7 +122,7 @@ jobs:
|
|||||||
choco install llvm --version ${{ matrix.llvm_choco_version }} --allow-downgrade
|
choco install llvm --version ${{ matrix.llvm_choco_version }} --allow-downgrade
|
||||||
cd 'C:\Program Files\LLVM\'
|
cd 'C:\Program Files\LLVM\'
|
||||||
LLVM_DIR=$(pwd)
|
LLVM_DIR=$(pwd)
|
||||||
echo "LLVM_SYS_110_PREFIX=${LLVM_DIR}" >> $GITHUB_ENV
|
echo "LLVM_SYS_120_PREFIX=${LLVM_DIR}" >> $GITHUB_ENV
|
||||||
- name: Install LLVM (macOS Apple Silicon)
|
- name: Install LLVM (macOS Apple Silicon)
|
||||||
if: matrix.os == 'macos-11.0' && !matrix.llvm_url
|
if: matrix.os == 'macos-11.0' && !matrix.llvm_url
|
||||||
run: |
|
run: |
|
||||||
@@ -131,12 +131,12 @@ jobs:
|
|||||||
if: matrix.llvm_url
|
if: matrix.llvm_url
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
curl --proto '=https' --tlsv1.2 -sSf ${{ matrix.llvm_url }} -L -o llvm.tar.gz
|
curl --proto '=https' --tlsv1.2 -sSf ${{ matrix.llvm_url }} -L -o llvm.tar.xz
|
||||||
LLVM_DIR=$(pwd)/${{ env.LLVM_DIR }}
|
LLVM_DIR=$(pwd)/${{ env.LLVM_DIR }}
|
||||||
mkdir ${LLVM_DIR}
|
mkdir ${LLVM_DIR}
|
||||||
tar xf llvm.tar.gz --strip-components=1 -C ${LLVM_DIR}
|
tar xf llvm.tar.xz --strip-components=1 -C ${LLVM_DIR}
|
||||||
echo "${LLVM_DIR}/bin" >> $GITHUB_PATH
|
echo "${LLVM_DIR}/bin" >> $GITHUB_PATH
|
||||||
echo "LLVM_SYS_110_PREFIX=${LLVM_DIR}" >> $GITHUB_ENV
|
echo "LLVM_SYS_120_PREFIX=${LLVM_DIR}" >> $GITHUB_ENV
|
||||||
env:
|
env:
|
||||||
LLVM_DIR: .llvm
|
LLVM_DIR: .llvm
|
||||||
- name: Set up dependencies for Mac OS
|
- name: Set up dependencies for Mac OS
|
||||||
|
|||||||
54
Cargo.lock
generated
54
Cargo.lock
generated
@@ -210,6 +210,27 @@ version = "3.7.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c59e7af012c713f529e7a3ee57ce9b31ddd858d4b512923602f74608b009631"
|
checksum = "9c59e7af012c713f529e7a3ee57ce9b31ddd858d4b512923602f74608b009631"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bytecheck"
|
||||||
|
version = "0.6.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fb738a1e65989ecdcd5bba16079641bd7209688fa546e1064832fd6e012fd32a"
|
||||||
|
dependencies = [
|
||||||
|
"bytecheck_derive",
|
||||||
|
"ptr_meta",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bytecheck_derive"
|
||||||
|
version = "0.6.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c3b4dff26fdc9f847dab475c9fec16f2cba82d5aa1f09981b87c44520721e10a"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
version = "1.4.3"
|
version = "1.4.3"
|
||||||
@@ -1156,9 +1177,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "llvm-sys"
|
name = "llvm-sys"
|
||||||
version = "110.0.2"
|
version = "120.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3b7cc88ba864d592f52132ed3a19a97118fe16c92a63961f54b0ab7279c5407f"
|
checksum = "b4a810627ac62b396f5fd2214ba9bbd8748d4d6efdc4d2c1c1303ea7a75763ce"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
@@ -1773,22 +1794,33 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rkyv"
|
name = "rend"
|
||||||
version = "0.6.7"
|
version = "0.3.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cb135b3e5e3311f0a254bfb00333f4bac9ef1d89888b84242a89eb8722b09a07"
|
checksum = "6d0351a2e529ee30d571ef31faa5a4e0b9addaad087697b77efb20d2809e41c7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memoffset",
|
"bytecheck",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rkyv"
|
||||||
|
version = "0.7.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e419b2e30d088b21c4bf3072561535305df8066e89937ad05fc205b99874c23c"
|
||||||
|
dependencies = [
|
||||||
|
"bytecheck",
|
||||||
|
"hashbrown 0.11.2",
|
||||||
"ptr_meta",
|
"ptr_meta",
|
||||||
|
"rend",
|
||||||
"rkyv_derive",
|
"rkyv_derive",
|
||||||
"seahash",
|
"seahash",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rkyv_derive"
|
name = "rkyv_derive"
|
||||||
version = "0.6.7"
|
version = "0.7.20"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ba8f489f6b6d8551bb15904293c1ad58a6abafa7d8390d15f7ed05a2afcd87d5"
|
checksum = "2ae58c4ba80f15f2f0842f4c61729e92c4e33a09bd78196c2b1ab9b0771a3ddf"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -2723,7 +2755,6 @@ dependencies = [
|
|||||||
"lazy_static",
|
"lazy_static",
|
||||||
"libc",
|
"libc",
|
||||||
"paste",
|
"paste",
|
||||||
"rayon",
|
|
||||||
"serde",
|
"serde",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"typetag",
|
"typetag",
|
||||||
@@ -2901,6 +2932,7 @@ name = "wasmer-engine"
|
|||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"backtrace",
|
"backtrace",
|
||||||
|
"enumset",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"loupe",
|
"loupe",
|
||||||
"memmap2",
|
"memmap2",
|
||||||
@@ -2920,6 +2952,7 @@ name = "wasmer-engine-dummy"
|
|||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bincode",
|
"bincode",
|
||||||
|
"enumset",
|
||||||
"loupe",
|
"loupe",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_bytes",
|
"serde_bytes",
|
||||||
@@ -2934,6 +2967,7 @@ name = "wasmer-engine-dylib"
|
|||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
|
"enumset",
|
||||||
"leb128",
|
"leb128",
|
||||||
"libloading",
|
"libloading",
|
||||||
"loupe",
|
"loupe",
|
||||||
@@ -2955,6 +2989,7 @@ version = "2.0.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"bincode",
|
"bincode",
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
|
"enumset",
|
||||||
"leb128",
|
"leb128",
|
||||||
"libloading",
|
"libloading",
|
||||||
"loupe",
|
"loupe",
|
||||||
@@ -2973,6 +3008,7 @@ name = "wasmer-engine-universal"
|
|||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
|
"enumset",
|
||||||
"leb128",
|
"leb128",
|
||||||
"loupe",
|
"loupe",
|
||||||
"region",
|
"region",
|
||||||
|
|||||||
17
Makefile
17
Makefile
@@ -134,24 +134,19 @@ ifneq ($(ENABLE_LLVM), 0)
|
|||||||
LLVM_VERSION := $(shell llvm-config --version)
|
LLVM_VERSION := $(shell llvm-config --version)
|
||||||
|
|
||||||
# If findstring is not empty, then it have found the value
|
# If findstring is not empty, then it have found the value
|
||||||
ifneq (, $(findstring 12,$(LLVM_VERSION)))
|
ifneq (, $(findstring 13,$(LLVM_VERSION)))
|
||||||
compilers += llvm
|
compilers += llvm
|
||||||
else ifneq (, $(findstring 11,$(LLVM_VERSION)))
|
else ifneq (, $(findstring 12,$(LLVM_VERSION)))
|
||||||
compilers += llvm
|
|
||||||
else ifneq (, $(findstring 10,$(LLVM_VERSION)))
|
|
||||||
compilers += llvm
|
compilers += llvm
|
||||||
endif
|
endif
|
||||||
# … or try to autodetect LLVM from `llvm-config-<version>`.
|
# … or try to autodetect LLVM from `llvm-config-<version>`.
|
||||||
else
|
else
|
||||||
ifneq (, $(shell which llvm-config-12 2>/dev/null))
|
ifneq (, $(shell which llvm-config-13 2>/dev/null))
|
||||||
|
LLVM_VERSION := $(shell llvm-config-13 --version)
|
||||||
|
compilers += llvm
|
||||||
|
else ifneq (, $(shell which llvm-config-12 2>/dev/null))
|
||||||
LLVM_VERSION := $(shell llvm-config-12 --version)
|
LLVM_VERSION := $(shell llvm-config-12 --version)
|
||||||
compilers += llvm
|
compilers += llvm
|
||||||
else ifneq (, $(shell which llvm-config-11 2>/dev/null))
|
|
||||||
LLVM_VERSION := $(shell llvm-config-11 --version)
|
|
||||||
compilers += llvm
|
|
||||||
else ifneq (, $(shell which llvm-config-10 2>/dev/null))
|
|
||||||
LLVM_VERSION := $(shell llvm-config-10 --version)
|
|
||||||
compilers += llvm
|
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|||||||
@@ -57,3 +57,8 @@ required-features = ["universal", "cranelift"]
|
|||||||
name = "dylib_cranelift"
|
name = "dylib_cranelift"
|
||||||
path = "fuzz_targets/dylib_cranelift.rs"
|
path = "fuzz_targets/dylib_cranelift.rs"
|
||||||
required-features = ["dylib", "cranelift"]
|
required-features = ["dylib", "cranelift"]
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "deterministic"
|
||||||
|
path = "fuzz_targets/deterministic.rs"
|
||||||
|
required-features = ["universal", "dylib", "cranelift", "llvm", "singlepass"]
|
||||||
81
fuzz/fuzz_targets/deterministic.rs
Normal file
81
fuzz/fuzz_targets/deterministic.rs
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
#![no_main]
|
||||||
|
|
||||||
|
use libfuzzer_sys::{arbitrary, arbitrary::Arbitrary, fuzz_target};
|
||||||
|
use wasm_smith::{Config, ConfiguredModule};
|
||||||
|
use wasmer::{CompilerConfig, Engine, Module, Store};
|
||||||
|
use wasmer_compiler_cranelift::Cranelift;
|
||||||
|
use wasmer_compiler_llvm::LLVM;
|
||||||
|
use wasmer_compiler_singlepass::Singlepass;
|
||||||
|
use wasmer_engine_dylib::Dylib;
|
||||||
|
use wasmer_engine_universal::Universal;
|
||||||
|
|
||||||
|
#[derive(Arbitrary, Debug, Default, Copy, Clone)]
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compile_and_compare(name: &str, engine: impl Engine, wasm: &[u8]) {
|
||||||
|
let store = Store::new(&engine);
|
||||||
|
|
||||||
|
// compile for first time
|
||||||
|
let module = Module::new(&store, wasm).unwrap();
|
||||||
|
let first = module.serialize().unwrap();
|
||||||
|
|
||||||
|
// compile for second time
|
||||||
|
let module = Module::new(&store, wasm).unwrap();
|
||||||
|
let second = module.serialize().unwrap();
|
||||||
|
|
||||||
|
if first != second {
|
||||||
|
panic!("non-deterministic compilation from {}", name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fuzz_target!(|module: ConfiguredModule<NoImportsConfig>| {
|
||||||
|
let wasm_bytes = module.to_bytes();
|
||||||
|
|
||||||
|
let mut compiler = Cranelift::default();
|
||||||
|
compiler.canonicalize_nans(true);
|
||||||
|
compiler.enable_verifier();
|
||||||
|
compile_and_compare(
|
||||||
|
"universal-cranelift",
|
||||||
|
Universal::new(compiler.clone()).engine(),
|
||||||
|
&wasm_bytes,
|
||||||
|
);
|
||||||
|
//compile_and_compare(
|
||||||
|
// "dylib-cranelift",
|
||||||
|
// Dylib::new(compiler).engine(),
|
||||||
|
// &wasm_bytes,
|
||||||
|
//);
|
||||||
|
|
||||||
|
let mut compiler = LLVM::default();
|
||||||
|
compiler.canonicalize_nans(true);
|
||||||
|
compiler.enable_verifier();
|
||||||
|
compile_and_compare(
|
||||||
|
"universal-llvm",
|
||||||
|
Universal::new(compiler.clone()).engine(),
|
||||||
|
&wasm_bytes,
|
||||||
|
);
|
||||||
|
//compile_and_compare("dylib-llvm", Dylib::new(compiler).engine(), &wasm_bytes);
|
||||||
|
|
||||||
|
let compiler = Singlepass::default();
|
||||||
|
compile_and_compare(
|
||||||
|
"universal-singlepass",
|
||||||
|
Universal::new(compiler.clone()).engine(),
|
||||||
|
&wasm_bytes,
|
||||||
|
);
|
||||||
|
//compile_and_compare(
|
||||||
|
// "dylib-singlepass",
|
||||||
|
// Dylib::new(compiler).engine(),
|
||||||
|
// &wasm_bytes,
|
||||||
|
//);
|
||||||
|
});
|
||||||
2
lib/api/src/js/externals/function.rs
vendored
2
lib/api/src/js/externals/function.rs
vendored
@@ -1288,7 +1288,7 @@ mod inner {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_into_array() {
|
fn test_into_array() {
|
||||||
assert_eq!(().into_array(), []);
|
assert_eq!(().into_array(), [0i128; 0]);
|
||||||
assert_eq!((1).into_array(), [1]);
|
assert_eq!((1).into_array(), [1]);
|
||||||
assert_eq!((1i32, 2i64).into_array(), [1, 2]);
|
assert_eq!((1i32, 2i64).into_array(), [1, 2]);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|||||||
2
lib/api/src/sys/externals/function.rs
vendored
2
lib/api/src/sys/externals/function.rs
vendored
@@ -1472,7 +1472,7 @@ mod inner {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_into_array() {
|
fn test_into_array() {
|
||||||
assert_eq!(().into_array(), []);
|
assert_eq!(().into_array(), [0i128; 0]);
|
||||||
assert_eq!((1).into_array(), [1]);
|
assert_eq!((1).into_array(), [1]);
|
||||||
assert_eq!((1i32, 2i64).into_array(), [1, 2]);
|
assert_eq!((1i32, 2i64).into_array(), [1, 2]);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|||||||
@@ -58,6 +58,11 @@ pub enum InstantiationError {
|
|||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Start(RuntimeError),
|
Start(RuntimeError),
|
||||||
|
|
||||||
|
/// The module was compiled with a CPU feature that is not available on
|
||||||
|
/// the current host.
|
||||||
|
#[error("missing requires CPU features: {0:?}")]
|
||||||
|
CpuFeature(String),
|
||||||
|
|
||||||
/// Error occurred when initializing the host environment.
|
/// Error occurred when initializing the host environment.
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
HostEnvInitialization(HostEnvInitError),
|
HostEnvInitialization(HostEnvInitError),
|
||||||
@@ -68,6 +73,7 @@ impl From<wasmer_engine::InstantiationError> for InstantiationError {
|
|||||||
match other {
|
match other {
|
||||||
wasmer_engine::InstantiationError::Link(e) => Self::Link(e),
|
wasmer_engine::InstantiationError::Link(e) => Self::Link(e),
|
||||||
wasmer_engine::InstantiationError::Start(e) => Self::Start(e),
|
wasmer_engine::InstantiationError::Start(e) => Self::Start(e),
|
||||||
|
wasmer_engine::InstantiationError::CpuFeature(e) => Self::CpuFeature(e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,6 @@ serde = { version = "1", optional = true, features = ["derive"] }
|
|||||||
thiserror = "1"
|
thiserror = "1"
|
||||||
typetag = { version = "0.1", optional = true }
|
typetag = { version = "0.1", optional = true }
|
||||||
paste = "1.0"
|
paste = "1.0"
|
||||||
rayon = "1.5"
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
field-offset = "0.3.3"
|
field-offset = "0.3.3"
|
||||||
|
|||||||
@@ -103,12 +103,15 @@ int main(int argc, const char* argv[]) {
|
|||||||
wasmer_last_error_message(error_message, error_length);
|
wasmer_last_error_message(error_message, error_length);
|
||||||
|
|
||||||
printf("Attempted to set an immutable global: `%s`\n", error_message);
|
printf("Attempted to set an immutable global: `%s`\n", error_message);
|
||||||
|
free(error_message);
|
||||||
}
|
}
|
||||||
|
|
||||||
wasm_val_t some_set_value = WASM_F32_VAL(21);
|
wasm_val_t some_set_value = WASM_F32_VAL(21);
|
||||||
wasm_global_set(some, &some_set_value);
|
wasm_global_set(some, &some_set_value);
|
||||||
printf("`some` value: %.1f\n", some_value.of.f32);
|
printf("`some` value: %.1f\n", some_value.of.f32);
|
||||||
|
|
||||||
|
wasm_globaltype_delete(one_type);
|
||||||
|
wasm_globaltype_delete(some_type);
|
||||||
wasm_module_delete(module);
|
wasm_module_delete(module);
|
||||||
wasm_extern_vec_delete(&exports);
|
wasm_extern_vec_delete(&exports);
|
||||||
wasm_instance_delete(instance);
|
wasm_instance_delete(instance);
|
||||||
|
|||||||
@@ -63,6 +63,8 @@ int main(int argc, const char* argv[]) {
|
|||||||
|
|
||||||
printf("Instantiating module...\n");
|
printf("Instantiating module...\n");
|
||||||
wasm_instance_t* instance = wasm_instance_new(store, module, &import_object, NULL);
|
wasm_instance_t* instance = wasm_instance_new(store, module, &import_object, NULL);
|
||||||
|
wasm_func_delete(host_func);
|
||||||
|
wasm_global_delete(host_global);
|
||||||
|
|
||||||
if (!instance) {
|
if (!instance) {
|
||||||
printf("> Error instantiating module!\n");
|
printf("> Error instantiating module!\n");
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
wasm_byte_vec_new(&wat, strlen(wat_string), wat_string);
|
wasm_byte_vec_new(&wat, strlen(wat_string), wat_string);
|
||||||
wasm_byte_vec_t wasm_bytes;
|
wasm_byte_vec_t wasm_bytes;
|
||||||
wat2wasm(&wat, &wasm_bytes);
|
wat2wasm(&wat, &wasm_bytes);
|
||||||
|
wasm_byte_vec_delete(&wat);
|
||||||
|
|
||||||
printf("Creating the store...\n");
|
printf("Creating the store...\n");
|
||||||
wasm_engine_t* engine = wasm_engine_new();
|
wasm_engine_t* engine = wasm_engine_new();
|
||||||
|
|||||||
@@ -69,13 +69,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
|
|
||||||
// Instantiate.
|
// Instantiate.
|
||||||
printf("Instantiating module...\n");
|
printf("Instantiating module...\n");
|
||||||
wasm_importtype_vec_t import_types;
|
|
||||||
wasm_module_imports(module, &import_types);
|
|
||||||
|
|
||||||
wasm_extern_vec_t imports;
|
wasm_extern_vec_t imports;
|
||||||
wasm_extern_vec_new_uninitialized(&imports, import_types.size);
|
|
||||||
wasm_importtype_vec_delete(&import_types);
|
|
||||||
|
|
||||||
bool get_imports_result = wasi_get_imports(store, module, wasi_env, &imports);
|
bool get_imports_result = wasi_get_imports(store, module, wasi_env, &imports);
|
||||||
|
|
||||||
if (!get_imports_result) {
|
if (!get_imports_result) {
|
||||||
@@ -153,6 +147,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
fclose(memory_stream);
|
fclose(memory_stream);
|
||||||
|
|
||||||
printf("WASI Stdout: `%.*s`\n", (int) stdout_size, stdout);
|
printf("WASI Stdout: `%.*s`\n", (int) stdout_size, stdout);
|
||||||
|
free(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -49,13 +49,12 @@
|
|||||||
|
|
||||||
use libc::{c_char, c_int};
|
use libc::{c_char, c_int};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::error::Error;
|
use std::fmt::Display;
|
||||||
use std::fmt::{self, Display, Formatter};
|
|
||||||
use std::ptr::{self, NonNull};
|
use std::ptr::{self, NonNull};
|
||||||
use std::slice;
|
use std::slice;
|
||||||
|
|
||||||
thread_local! {
|
thread_local! {
|
||||||
static LAST_ERROR: RefCell<Option<Box<dyn Error>>> = RefCell::new(None);
|
static LAST_ERROR: RefCell<Option<String>> = RefCell::new(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Rust function to register a new error.
|
/// Rust function to register a new error.
|
||||||
@@ -63,24 +62,23 @@ thread_local! {
|
|||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```rust,no_run
|
/// ```rust,no_run
|
||||||
/// # use wasmer::error::{update_last_error, CApiError};
|
/// # use wasmer::error::update_last_error;
|
||||||
///
|
///
|
||||||
/// update_last_error(CApiError {
|
/// update_last_error("Hello, World!");
|
||||||
/// msg: "Hello, World!".to_string(),
|
|
||||||
/// });
|
|
||||||
/// ```
|
/// ```
|
||||||
pub fn update_last_error<E: Error + 'static>(err: E) {
|
pub fn update_last_error<E: Display>(err: E) {
|
||||||
LAST_ERROR.with(|prev| {
|
LAST_ERROR.with(|prev| {
|
||||||
*prev.borrow_mut() = Some(Box::new(err));
|
*prev.borrow_mut() = Some(err.to_string());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieve the most recent error, clearing it in the process.
|
/// Retrieve the most recent error, clearing it in the process.
|
||||||
pub(crate) fn take_last_error() -> Option<Box<dyn Error>> {
|
pub(crate) fn take_last_error() -> Option<String> {
|
||||||
LAST_ERROR.with(|prev| prev.borrow_mut().take())
|
LAST_ERROR.with(|prev| prev.borrow_mut().take())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the length in bytes of the last error if any, zero otherwise.
|
/// Gets the length in bytes of the last error if any, zero otherwise. This
|
||||||
|
/// includes th NUL terminator byte.
|
||||||
///
|
///
|
||||||
/// This can be used to dynamically allocate a buffer with the correct number of
|
/// This can be used to dynamically allocate a buffer with the correct number of
|
||||||
/// bytes needed to store a message.
|
/// bytes needed to store a message.
|
||||||
@@ -88,10 +86,11 @@ pub(crate) fn take_last_error() -> Option<Box<dyn Error>> {
|
|||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// See this module's documentation to get a complete example.
|
/// See this module's documentation to get a complete example.
|
||||||
|
// TODO(Amanieu): This should use size_t
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wasmer_last_error_length() -> c_int {
|
pub extern "C" fn wasmer_last_error_length() -> c_int {
|
||||||
LAST_ERROR.with(|prev| match *prev.borrow() {
|
LAST_ERROR.with(|prev| match *prev.borrow() {
|
||||||
Some(ref err) => err.to_string().len() as c_int + 1,
|
Some(ref err) => err.len() as c_int + 1,
|
||||||
None => 0,
|
None => 0,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -118,6 +117,7 @@ pub extern "C" fn wasmer_last_error_length() -> c_int {
|
|||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// See this module's documentation to get a complete example.
|
/// See this module's documentation to get a complete example.
|
||||||
|
// TODO(Amanieu): This should use size_t
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasmer_last_error_message(
|
pub unsafe extern "C" fn wasmer_last_error_message(
|
||||||
buffer: Option<NonNull<c_char>>,
|
buffer: Option<NonNull<c_char>>,
|
||||||
@@ -156,18 +156,3 @@ pub unsafe extern "C" fn wasmer_last_error_message(
|
|||||||
|
|
||||||
error_message.len() as c_int + 1
|
error_message.len() as c_int + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Rust type to represent a C API error.
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct CApiError {
|
|
||||||
/// The error message.
|
|
||||||
pub msg: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for CApiError {
|
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
|
||||||
write!(f, "{}", &self.msg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Error for CApiError {}
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
//! This resolver is used in the Wasm-C-API as the imports are provided
|
//! This resolver is used in the Wasm-C-API as the imports are provided
|
||||||
//! by index and not by module and name.
|
//! by index and not by module and name.
|
||||||
|
|
||||||
use rayon::iter::{FromParallelIterator, IntoParallelIterator, ParallelIterator};
|
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
use wasmer_api::{Export, Exportable, Extern, Resolver};
|
use wasmer_api::{Export, Exportable, Extern, Resolver};
|
||||||
|
|
||||||
@@ -26,16 +25,10 @@ impl Resolver for OrderedResolver {
|
|||||||
|
|
||||||
impl FromIterator<Extern> for OrderedResolver {
|
impl FromIterator<Extern> for OrderedResolver {
|
||||||
fn from_iter<I: IntoIterator<Item = Extern>>(iter: I) -> Self {
|
fn from_iter<I: IntoIterator<Item = Extern>>(iter: I) -> Self {
|
||||||
OrderedResolver {
|
let mut externs = Vec::new();
|
||||||
externs: iter.into_iter().collect(),
|
for extern_ in iter {
|
||||||
}
|
externs.push(extern_);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromParallelIterator<Extern> for OrderedResolver {
|
|
||||||
fn from_par_iter<I: IntoParallelIterator<Item = Extern>>(iter: I) -> Self {
|
|
||||||
OrderedResolver {
|
|
||||||
externs: iter.into_par_iter().collect(),
|
|
||||||
}
|
}
|
||||||
|
OrderedResolver { externs }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ pub use super::unstable::middlewares::wasm_config_push_middleware;
|
|||||||
#[cfg(feature = "middlewares")]
|
#[cfg(feature = "middlewares")]
|
||||||
use super::unstable::middlewares::wasmer_middleware_t;
|
use super::unstable::middlewares::wasmer_middleware_t;
|
||||||
use super::unstable::target_lexicon::wasmer_target_t;
|
use super::unstable::target_lexicon::wasmer_target_t;
|
||||||
use crate::error::{update_last_error, CApiError};
|
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;
|
||||||
@@ -433,13 +433,8 @@ pub extern "C" fn wasm_engine_new_with_config(
|
|||||||
config: Option<Box<wasm_config_t>>,
|
config: Option<Box<wasm_config_t>>,
|
||||||
) -> Option<Box<wasm_engine_t>> {
|
) -> Option<Box<wasm_engine_t>> {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn return_with_error<M>(msg: M) -> Option<Box<wasm_engine_t>>
|
fn return_with_error(msg: &str) -> Option<Box<wasm_engine_t>> {
|
||||||
where
|
update_last_error(msg);
|
||||||
M: ToString,
|
|
||||||
{
|
|
||||||
update_last_error(CApiError {
|
|
||||||
msg: msg.to_string(),
|
|
||||||
});
|
|
||||||
|
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|||||||
77
lib/c-api/src/wasm_c_api/externals/function.rs
vendored
77
lib/c-api/src/wasm_c_api/externals/function.rs
vendored
@@ -5,6 +5,7 @@ use super::super::value::{wasm_val_inner, wasm_val_t, wasm_val_vec_t};
|
|||||||
use super::CApiExternTag;
|
use super::CApiExternTag;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::ffi::c_void;
|
use std::ffi::c_void;
|
||||||
|
use std::mem::MaybeUninit;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use wasmer_api::{Function, RuntimeError, Val};
|
use wasmer_api::{Function, RuntimeError, Val};
|
||||||
|
|
||||||
@@ -27,16 +28,16 @@ impl wasm_func_t {
|
|||||||
|
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
pub type wasm_func_callback_t = unsafe extern "C" fn(
|
pub type wasm_func_callback_t = unsafe extern "C" fn(
|
||||||
args: *const wasm_val_vec_t,
|
args: &wasm_val_vec_t,
|
||||||
results: *mut wasm_val_vec_t,
|
results: &mut wasm_val_vec_t,
|
||||||
) -> *mut wasm_trap_t;
|
) -> Option<Box<wasm_trap_t>>;
|
||||||
|
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
pub type wasm_func_callback_with_env_t = unsafe extern "C" fn(
|
pub type wasm_func_callback_with_env_t = unsafe extern "C" fn(
|
||||||
env: *mut c_void,
|
env: *mut c_void,
|
||||||
args: *const wasm_val_vec_t,
|
args: &wasm_val_vec_t,
|
||||||
results: *mut wasm_val_vec_t,
|
results: &mut wasm_val_vec_t,
|
||||||
) -> *mut wasm_trap_t;
|
) -> Option<Box<wasm_trap_t>>;
|
||||||
|
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
pub type wasm_env_finalizer_t = unsafe extern "C" fn(*mut c_void);
|
pub type wasm_env_finalizer_t = unsafe extern "C" fn(*mut c_void);
|
||||||
@@ -72,15 +73,12 @@ pub unsafe extern "C" fn wasm_func_new(
|
|||||||
|
|
||||||
let trap = callback(&processed_args, &mut results);
|
let trap = callback(&processed_args, &mut results);
|
||||||
|
|
||||||
if !trap.is_null() {
|
if let Some(trap) = trap {
|
||||||
let trap: Box<wasm_trap_t> = Box::from_raw(trap);
|
|
||||||
|
|
||||||
return Err(trap.inner);
|
return Err(trap.inner);
|
||||||
}
|
}
|
||||||
|
|
||||||
let processed_results = results
|
let processed_results = results
|
||||||
.into_slice()
|
.take()
|
||||||
.expect("Failed to convert `results` into a slice")
|
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(TryInto::try_into)
|
.map(TryInto::try_into)
|
||||||
.collect::<Result<Vec<Val>, _>>()
|
.collect::<Result<Vec<Val>, _>>()
|
||||||
@@ -124,12 +122,8 @@ pub unsafe extern "C" fn wasm_func_new_with_env(
|
|||||||
|
|
||||||
impl Drop for WrapperEnv {
|
impl Drop for WrapperEnv {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if let Some(env_finalizer) =
|
if let Some(env_finalizer) = *self.env_finalizer {
|
||||||
Arc::get_mut(&mut self.env_finalizer).and_then(Option::take)
|
unsafe { (env_finalizer)(self.env as _) }
|
||||||
{
|
|
||||||
if !self.env.is_null() {
|
|
||||||
unsafe { (env_finalizer)(self.env as _) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -153,15 +147,12 @@ pub unsafe extern "C" fn wasm_func_new_with_env(
|
|||||||
|
|
||||||
let trap = callback(env.env, &processed_args, &mut results);
|
let trap = callback(env.env, &processed_args, &mut results);
|
||||||
|
|
||||||
if !trap.is_null() {
|
if let Some(trap) = trap {
|
||||||
let trap: Box<wasm_trap_t> = Box::from_raw(trap);
|
|
||||||
|
|
||||||
return Err(trap.inner);
|
return Err(trap.inner);
|
||||||
}
|
}
|
||||||
|
|
||||||
let processed_results = results
|
let processed_results = results
|
||||||
.into_slice()
|
.take()
|
||||||
.expect("Failed to convert `results` into a slice")
|
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(TryInto::try_into)
|
.map(TryInto::try_into)
|
||||||
.collect::<Result<Vec<Val>, _>>()
|
.collect::<Result<Vec<Val>, _>>()
|
||||||
@@ -201,39 +192,21 @@ pub unsafe extern "C" fn wasm_func_call(
|
|||||||
let args = args?;
|
let args = args?;
|
||||||
|
|
||||||
let params = args
|
let params = args
|
||||||
.into_slice()
|
.as_slice()
|
||||||
.map(|slice| {
|
.iter()
|
||||||
slice
|
.cloned()
|
||||||
.into_iter()
|
.map(TryInto::try_into)
|
||||||
.map(TryInto::try_into)
|
.collect::<Result<Vec<Val>, _>>()
|
||||||
.collect::<Result<Vec<Val>, _>>()
|
.expect("Arguments conversion failed");
|
||||||
.expect("Arguments conversion failed")
|
|
||||||
})
|
|
||||||
.unwrap_or_default();
|
|
||||||
|
|
||||||
match func.inner.call(¶ms) {
|
match func.inner.call(¶ms) {
|
||||||
Ok(wasm_results) => {
|
Ok(wasm_results) => {
|
||||||
let vals = wasm_results
|
for (slot, val) in results
|
||||||
.into_iter()
|
.as_uninit_slice()
|
||||||
.map(TryInto::try_into)
|
.iter_mut()
|
||||||
.collect::<Result<Vec<wasm_val_t>, _>>()
|
.zip(wasm_results.into_iter())
|
||||||
.expect("Results conversion failed");
|
{
|
||||||
|
*slot = MaybeUninit::new(val.try_into().expect("Results conversion failed"));
|
||||||
// `results` is an uninitialized vector. Set a new value.
|
|
||||||
if results.is_uninitialized() {
|
|
||||||
*results = vals.into();
|
|
||||||
}
|
|
||||||
// `results` is an initialized but empty vector. Fill it
|
|
||||||
// item per item.
|
|
||||||
else {
|
|
||||||
let slice = results
|
|
||||||
.into_slice_mut()
|
|
||||||
.expect("`wasm_func_call`, results' size is greater than 0 but data is NULL");
|
|
||||||
|
|
||||||
for (result, value) in slice.iter_mut().zip(vals.iter()) {
|
|
||||||
(*result).kind = value.kind;
|
|
||||||
(*result).of = value.of;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
None
|
None
|
||||||
|
|||||||
1
lib/c-api/src/wasm_c_api/externals/global.rs
vendored
1
lib/c-api/src/wasm_c_api/externals/global.rs
vendored
@@ -48,7 +48,6 @@ pub unsafe extern "C" fn wasm_global_new(
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasm_global_delete(_global: Option<Box<wasm_global_t>>) {}
|
pub unsafe extern "C" fn wasm_global_delete(_global: Option<Box<wasm_global_t>>) {}
|
||||||
|
|
||||||
// TODO: figure out if these should be deep or shallow copies
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasm_global_copy(global: &wasm_global_t) -> Box<wasm_global_t> {
|
pub unsafe extern "C" fn wasm_global_copy(global: &wasm_global_t) -> Box<wasm_global_t> {
|
||||||
// do shallow copy
|
// do shallow copy
|
||||||
|
|||||||
1
lib/c-api/src/wasm_c_api/externals/memory.rs
vendored
1
lib/c-api/src/wasm_c_api/externals/memory.rs
vendored
@@ -38,7 +38,6 @@ pub unsafe extern "C" fn wasm_memory_new(
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasm_memory_delete(_memory: Option<Box<wasm_memory_t>>) {}
|
pub unsafe extern "C" fn wasm_memory_delete(_memory: Option<Box<wasm_memory_t>>) {}
|
||||||
|
|
||||||
// TODO: figure out if these should be deep or shallow copies
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasm_memory_copy(memory: &wasm_memory_t) -> Box<wasm_memory_t> {
|
pub unsafe extern "C" fn wasm_memory_copy(memory: &wasm_memory_t) -> Box<wasm_memory_t> {
|
||||||
// do shallow copy
|
// do shallow copy
|
||||||
|
|||||||
26
lib/c-api/src/wasm_c_api/externals/mod.rs
vendored
26
lib/c-api/src/wasm_c_api/externals/mod.rs
vendored
@@ -6,7 +6,7 @@ mod table;
|
|||||||
pub use function::*;
|
pub use function::*;
|
||||||
pub use global::*;
|
pub use global::*;
|
||||||
pub use memory::*;
|
pub use memory::*;
|
||||||
use std::mem;
|
use std::mem::{self, ManuallyDrop};
|
||||||
pub use table::*;
|
pub use table::*;
|
||||||
use wasmer_api::{Extern, ExternType};
|
use wasmer_api::{Extern, ExternType};
|
||||||
|
|
||||||
@@ -150,13 +150,23 @@ impl From<Extern> for wasm_extern_t {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl From<wasm_extern_t> for Extern {
|
impl From<wasm_extern_t> for Extern {
|
||||||
fn from(other: wasm_extern_t) -> Self {
|
fn from(mut other: wasm_extern_t) -> Self {
|
||||||
match other.get_tag() {
|
let out = match other.get_tag() {
|
||||||
CApiExternTag::Function => unsafe { (&*other.inner.function.inner).clone().into() },
|
CApiExternTag::Function => unsafe {
|
||||||
CApiExternTag::Memory => unsafe { (&*other.inner.memory.inner).clone().into() },
|
(*ManuallyDrop::take(&mut other.inner.function).inner).into()
|
||||||
CApiExternTag::Table => unsafe { (&*other.inner.table.inner).clone().into() },
|
},
|
||||||
CApiExternTag::Global => unsafe { (&*other.inner.global.inner).clone().into() },
|
CApiExternTag::Memory => unsafe {
|
||||||
}
|
(*ManuallyDrop::take(&mut other.inner.memory).inner).into()
|
||||||
|
},
|
||||||
|
CApiExternTag::Table => unsafe {
|
||||||
|
(*ManuallyDrop::take(&mut other.inner.table).inner).into()
|
||||||
|
},
|
||||||
|
CApiExternTag::Global => unsafe {
|
||||||
|
(*ManuallyDrop::take(&mut other.inner.global).inner).into()
|
||||||
|
},
|
||||||
|
};
|
||||||
|
mem::forget(other);
|
||||||
|
out
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
use super::externals::{wasm_extern_t, wasm_extern_vec_t};
|
use super::externals::wasm_extern_vec_t;
|
||||||
use super::module::wasm_module_t;
|
use super::module::wasm_module_t;
|
||||||
use super::store::wasm_store_t;
|
use super::store::wasm_store_t;
|
||||||
use super::trap::wasm_trap_t;
|
use super::trap::wasm_trap_t;
|
||||||
use crate::ordered_resolver::OrderedResolver;
|
use crate::ordered_resolver::OrderedResolver;
|
||||||
use rayon::prelude::*;
|
|
||||||
use std::mem;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use wasmer_api::{Extern, Instance, InstantiationError};
|
use wasmer_api::{Extern, Instance, InstantiationError};
|
||||||
|
|
||||||
@@ -42,7 +40,7 @@ pub unsafe extern "C" fn wasm_instance_new(
|
|||||||
_store: Option<&wasm_store_t>,
|
_store: Option<&wasm_store_t>,
|
||||||
module: Option<&wasm_module_t>,
|
module: Option<&wasm_module_t>,
|
||||||
imports: Option<&wasm_extern_vec_t>,
|
imports: Option<&wasm_extern_vec_t>,
|
||||||
trap: *mut *mut wasm_trap_t,
|
trap: Option<&mut *mut wasm_trap_t>,
|
||||||
) -> Option<Box<wasm_instance_t>> {
|
) -> Option<Box<wasm_instance_t>> {
|
||||||
let module = module?;
|
let module = module?;
|
||||||
let imports = imports?;
|
let imports = imports?;
|
||||||
@@ -51,10 +49,9 @@ pub unsafe extern "C" fn wasm_instance_new(
|
|||||||
let module_imports = wasm_module.imports();
|
let module_imports = wasm_module.imports();
|
||||||
let module_import_count = module_imports.len();
|
let module_import_count = module_imports.len();
|
||||||
let resolver: OrderedResolver = imports
|
let resolver: OrderedResolver = imports
|
||||||
.into_slice()
|
.as_slice()
|
||||||
.map(|imports| imports.par_iter())
|
.iter()
|
||||||
.unwrap_or_else(|| [].par_iter())
|
.map(|imp| Extern::from(imp.as_ref().unwrap().as_ref().clone()))
|
||||||
.map(|imp| Extern::from((&**imp).clone()))
|
|
||||||
.take(module_import_count)
|
.take(module_import_count)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
@@ -68,8 +65,16 @@ pub unsafe extern "C" fn wasm_instance_new(
|
|||||||
}
|
}
|
||||||
|
|
||||||
Err(InstantiationError::Start(runtime_error)) => {
|
Err(InstantiationError::Start(runtime_error)) => {
|
||||||
let this_trap: Box<wasm_trap_t> = Box::new(runtime_error.into());
|
if let Some(trap) = trap {
|
||||||
*trap = Box::into_raw(this_trap);
|
let this_trap: Box<wasm_trap_t> = Box::new(runtime_error.into());
|
||||||
|
*trap = Box::into_raw(this_trap);
|
||||||
|
}
|
||||||
|
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(e @ InstantiationError::CpuFeature(_)) => {
|
||||||
|
crate::error::update_last_error(e);
|
||||||
|
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
@@ -182,17 +187,13 @@ pub unsafe extern "C" fn wasm_instance_exports(
|
|||||||
out: &mut wasm_extern_vec_t,
|
out: &mut wasm_extern_vec_t,
|
||||||
) {
|
) {
|
||||||
let instance = &instance.inner;
|
let instance = &instance.inner;
|
||||||
let mut extern_vec = instance
|
let extern_vec = instance
|
||||||
.exports
|
.exports
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(_name, r#extern)| Box::into_raw(Box::new(r#extern.clone().into())))
|
.map(|(_name, r#extern)| Some(Box::new(r#extern.clone().into())))
|
||||||
.collect::<Vec<*mut wasm_extern_t>>();
|
.collect();
|
||||||
extern_vec.shrink_to_fit();
|
|
||||||
|
|
||||||
out.size = extern_vec.len();
|
out.set_buffer(extern_vec);
|
||||||
out.data = extern_vec.as_mut_ptr();
|
|
||||||
|
|
||||||
mem::forget(extern_vec);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -1,13 +1,121 @@
|
|||||||
#[doc(hidden)]
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! wasm_declare_vec_inner {
|
macro_rules! wasm_declare_vec_inner {
|
||||||
($name:ident) => {
|
(
|
||||||
wasm_declare_vec_inner!($name, wasm);
|
name: $name:ident,
|
||||||
};
|
ty: $elem_ty:ty,
|
||||||
|
c_ty: $c_ty:expr,
|
||||||
|
c_val: $c_val:expr,
|
||||||
|
new: $new:ident,
|
||||||
|
empty: $empty:ident,
|
||||||
|
uninit: $uninit:ident,
|
||||||
|
copy: $copy:ident,
|
||||||
|
delete: $delete:ident,
|
||||||
|
) => {
|
||||||
|
#[doc = concat!("Represents a vector of `", $c_ty, "`.
|
||||||
|
|
||||||
($name:ident, $prefix:ident) => {
|
Read the documentation of [`", $c_ty, "`] to see more concrete examples.
|
||||||
paste::paste! {
|
|
||||||
#[doc = "Creates an empty vector of [`" $prefix "_" $name "_t`].
|
# Example
|
||||||
|
|
||||||
|
```rust
|
||||||
|
# use inline_c::assert_c;
|
||||||
|
# fn main() {
|
||||||
|
# (assert_c! {
|
||||||
|
# #include \"tests/wasmer.h\"
|
||||||
|
#
|
||||||
|
void example(", $c_ty, " x, ", $c_ty, " y) {
|
||||||
|
// Create a vector of 2 `", $c_ty, "`.
|
||||||
|
", $c_ty, " items[2] = {x, y};
|
||||||
|
|
||||||
|
", stringify!($name), " vector;
|
||||||
|
", stringify!($new), "(&vector, 2, items);
|
||||||
|
|
||||||
|
// Check that it contains 2 items.
|
||||||
|
assert(vector.size == 2);
|
||||||
|
|
||||||
|
// Free it.
|
||||||
|
", stringify!($delete), "(&vector);
|
||||||
|
}
|
||||||
|
#
|
||||||
|
# int main() { example(", $c_val, ", ", $c_val, "); return 0; }
|
||||||
|
# })
|
||||||
|
# .success();
|
||||||
|
# }
|
||||||
|
```")]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct $name {
|
||||||
|
pub size: usize,
|
||||||
|
pub data: *mut $elem_ty,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl $name {
|
||||||
|
// Note that this does not free any existing buffer.
|
||||||
|
pub fn set_buffer(&mut self, buffer: Vec<$elem_ty>) {
|
||||||
|
let mut vec = buffer.into_boxed_slice();
|
||||||
|
self.size = vec.len();
|
||||||
|
self.data = vec.as_mut_ptr();
|
||||||
|
std::mem::forget(vec);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_slice(&self) -> &[$elem_ty] {
|
||||||
|
// Note that we're careful to not create a slice with a null
|
||||||
|
// pointer as the data pointer, since that isn't defined
|
||||||
|
// behavior in Rust.
|
||||||
|
if self.size == 0 {
|
||||||
|
&[]
|
||||||
|
} else {
|
||||||
|
assert!(!self.data.is_null());
|
||||||
|
unsafe { std::slice::from_raw_parts(self.data, self.size) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_uninit_slice(&mut self) -> &mut [std::mem::MaybeUninit<$elem_ty>] {
|
||||||
|
// Note that we're careful to not create a slice with a null
|
||||||
|
// pointer as the data pointer, since that isn't defined
|
||||||
|
// behavior in Rust.
|
||||||
|
if self.size == 0 {
|
||||||
|
&mut []
|
||||||
|
} else {
|
||||||
|
assert!(!self.data.is_null());
|
||||||
|
unsafe { std::slice::from_raw_parts_mut(self.data as _, self.size) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn take(&mut self) -> Vec<$elem_ty> {
|
||||||
|
if self.data.is_null() {
|
||||||
|
return Vec::new();
|
||||||
|
}
|
||||||
|
let vec = unsafe { Vec::from_raw_parts(self.data, self.size, self.size) };
|
||||||
|
self.data = std::ptr::null_mut();
|
||||||
|
self.size = 0;
|
||||||
|
return vec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Vec<$elem_ty>> for $name {
|
||||||
|
fn from(vec: Vec<$elem_ty>) -> Self {
|
||||||
|
let mut vec = vec.into_boxed_slice();
|
||||||
|
let result = $name {
|
||||||
|
size: vec.len(),
|
||||||
|
data: vec.as_mut_ptr(),
|
||||||
|
};
|
||||||
|
std::mem::forget(vec);
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clone for $name {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
self.as_slice().to_vec().into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for $name {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
drop(self.take());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc = concat!("Creates an empty vector of [`", $c_ty, "`].
|
||||||
|
|
||||||
# Example
|
# Example
|
||||||
|
|
||||||
@@ -18,31 +126,89 @@ macro_rules! wasm_declare_vec_inner {
|
|||||||
# #include \"tests/wasmer.h\"
|
# #include \"tests/wasmer.h\"
|
||||||
#
|
#
|
||||||
int main() {
|
int main() {
|
||||||
// Creates an empty vector of `" $prefix "_" $name "_t`.
|
// Creates an empty vector of `", $c_ty, "`.
|
||||||
" $prefix "_" $name "_vec_t vector;
|
", stringify!($name), " vector;
|
||||||
" $prefix "_" $name "_vec_new_empty(&vector);
|
", stringify!($empty), "(&vector);
|
||||||
|
|
||||||
// Check that it is empty.
|
// Check that it is empty.
|
||||||
assert(vector.size == 0);
|
assert(vector.size == 0);
|
||||||
|
|
||||||
// Free it.
|
// Free it.
|
||||||
" $prefix "_" $name "_vec_delete(&vector);
|
", stringify!($delete), "(&vector);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
# })
|
# })
|
||||||
# .success();
|
# .success();
|
||||||
# }
|
# }
|
||||||
```"]
|
```")]
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn [<$prefix _ $name _vec_new_empty>](out: *mut [<$prefix _ $name _vec_t>]) {
|
pub extern "C" fn $empty(out: &mut $name) {
|
||||||
// TODO: actually implement this
|
out.size = 0;
|
||||||
[<$prefix _ $name _vec_new_uninitialized>](out, 0);
|
out.data = std::ptr::null_mut();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
#[doc = concat!("Creates a new uninitialized vector of [`", $c_ty, "`].
|
||||||
|
|
||||||
|
# Example
|
||||||
|
|
||||||
|
```rust
|
||||||
|
# use inline_c::assert_c;
|
||||||
|
# fn main() {
|
||||||
|
# (assert_c! {
|
||||||
|
# #include \"tests/wasmer.h\"
|
||||||
|
#
|
||||||
|
int main() {
|
||||||
|
// Creates an empty vector of `", $c_ty, "`.
|
||||||
|
", stringify!($name), " vector;
|
||||||
|
", stringify!($uninit), "(&vector, 3);
|
||||||
|
|
||||||
|
// Check that it contains 3 items.
|
||||||
|
assert(vector.size == 3);
|
||||||
|
|
||||||
|
// Free it.
|
||||||
|
", stringify!($delete), "(&vector);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
# })
|
||||||
|
# .success();
|
||||||
|
# }
|
||||||
|
```")]
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn $uninit(out: &mut $name, size: usize) {
|
||||||
|
out.set_buffer(vec![Default::default(); size]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc = concat!("Creates a new vector of [`", $c_ty, "`].
|
||||||
|
|
||||||
|
# Example
|
||||||
|
|
||||||
|
See the [`", stringify!($name), "`] type to get an example.")]
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn $new(out: &mut $name, size: usize, ptr: *const $elem_ty) {
|
||||||
|
let vec = (0..size).map(|i| ptr.add(i).read()).collect();
|
||||||
|
out.set_buffer(vec);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc = concat!("Performs a deep copy of a vector of [`", $c_ty, "`].")]
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn $copy(out: &mut $name, src: &$name) {
|
||||||
|
out.set_buffer(src.as_slice().to_vec());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc = concat!("Deletes a vector of [`", $c_ty, "`].
|
||||||
|
|
||||||
|
# Example
|
||||||
|
|
||||||
|
See the [`", stringify!($name), "`] type to get an example.")]
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn $delete(out: &mut $name) {
|
||||||
|
out.take();
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! wasm_declare_vec {
|
macro_rules! wasm_declare_vec {
|
||||||
($name:ident) => {
|
($name:ident) => {
|
||||||
wasm_declare_vec!($name, wasm);
|
wasm_declare_vec!($name, wasm);
|
||||||
@@ -50,218 +216,25 @@ macro_rules! wasm_declare_vec {
|
|||||||
|
|
||||||
($name:ident, $prefix:ident) => {
|
($name:ident, $prefix:ident) => {
|
||||||
paste::paste! {
|
paste::paste! {
|
||||||
#[doc = "Represents a vector of `" $prefix "_" $name "_t`.
|
wasm_declare_vec_inner!(
|
||||||
|
name: [<$prefix _ $name _vec_t>],
|
||||||
Read the documentation of [`" $prefix "_" $name "_t`] to see more concrete examples.
|
ty: [<$prefix _ $name _t>],
|
||||||
|
c_ty: stringify!([<$prefix _ $name _t>]),
|
||||||
# Example
|
c_val: concat!("({ ",
|
||||||
|
stringify!([<$prefix _ $name _t>]), " foo;\n",
|
||||||
```rust
|
"memset(&foo, 0, sizeof(foo));\n",
|
||||||
# use inline_c::assert_c;
|
"foo;\n",
|
||||||
# fn main() {
|
"})"),
|
||||||
# (assert_c! {
|
new: [<$prefix _ $name _vec_new>],
|
||||||
# #include \"tests/wasmer.h\"
|
empty: [<$prefix _ $name _vec_new_empty>],
|
||||||
#
|
uninit: [<$prefix _ $name _vec_new_uninitialized>],
|
||||||
int main() {
|
copy: [<$prefix _ $name _vec_copy>],
|
||||||
// Create a vector of 2 `" $prefix "_" $name "_t`.
|
delete: [<$prefix _ $name _vec_delete>],
|
||||||
" $prefix "_" $name "_t x;
|
);
|
||||||
" $prefix "_" $name "_t y;
|
|
||||||
" $prefix "_" $name "_t* items[2] = {&x, &y};
|
|
||||||
|
|
||||||
" $prefix "_" $name "_vec_t vector;
|
|
||||||
" $prefix "_" $name "_vec_new(&vector, 2, (" $prefix "_" $name "_t*) items);
|
|
||||||
|
|
||||||
// Check that it contains 2 items.
|
|
||||||
assert(vector.size == 2);
|
|
||||||
|
|
||||||
// Free it.
|
|
||||||
" $prefix "_" $name "_vec_delete(&vector);
|
|
||||||
}
|
|
||||||
# })
|
|
||||||
# .success();
|
|
||||||
# }
|
|
||||||
```"]
|
|
||||||
#[derive(Debug)]
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct [<$prefix _ $name _vec_t>] {
|
|
||||||
pub size: usize,
|
|
||||||
pub data: *mut [<$prefix _ $name _t>],
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Clone for [<$prefix _ $name _vec_t>] {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
if self.data.is_null() {
|
|
||||||
return Self {
|
|
||||||
size: self.size,
|
|
||||||
data: ::std::ptr::null_mut(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
let data =
|
|
||||||
unsafe {
|
|
||||||
let vec = Vec::from_raw_parts(self.data, self.size, self.size);
|
|
||||||
let mut vec_copy = vec.clone().into_boxed_slice();
|
|
||||||
let new_ptr = vec_copy.as_mut_ptr();
|
|
||||||
|
|
||||||
::std::mem::forget(vec);
|
|
||||||
::std::mem::forget(vec_copy);
|
|
||||||
|
|
||||||
new_ptr
|
|
||||||
};
|
|
||||||
|
|
||||||
Self {
|
|
||||||
size: self.size,
|
|
||||||
data,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> From<Vec<[<$prefix _ $name _t>]>> for [<$prefix _ $name _vec_t>] {
|
|
||||||
fn from(mut vec: Vec<[<$prefix _ $name _t>]>) -> Self {
|
|
||||||
vec.shrink_to_fit();
|
|
||||||
|
|
||||||
let length = vec.len();
|
|
||||||
let pointer = vec.as_mut_ptr();
|
|
||||||
|
|
||||||
::std::mem::forget(vec);
|
|
||||||
|
|
||||||
Self {
|
|
||||||
size: length,
|
|
||||||
data: pointer,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T: Into<[<$prefix _ $name _t>]> + Clone> From<&'a [T]> for [<$prefix _ $name _vec_t>] {
|
|
||||||
fn from(other: &'a [T]) -> Self {
|
|
||||||
let size = other.len();
|
|
||||||
let mut copied_data = other
|
|
||||||
.iter()
|
|
||||||
.cloned()
|
|
||||||
.map(Into::into)
|
|
||||||
.collect::<Vec<[<$prefix _ $name _t>]>>()
|
|
||||||
.into_boxed_slice();
|
|
||||||
let data = copied_data.as_mut_ptr();
|
|
||||||
::std::mem::forget(copied_data);
|
|
||||||
|
|
||||||
Self {
|
|
||||||
size,
|
|
||||||
data,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl [<$prefix _ $name _vec_t>] {
|
|
||||||
pub unsafe fn into_slice(&self) -> Option<&[[<$prefix _ $name _t>]]>{
|
|
||||||
if self.is_uninitialized() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(::std::slice::from_raw_parts(self.data, self.size))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn into_slice_mut(&mut self) -> Option<&mut [[<$prefix _ $name _t>]]>{
|
|
||||||
if self.is_uninitialized() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(::std::slice::from_raw_parts_mut(self.data, self.size))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_uninitialized(&self) -> bool {
|
|
||||||
self.data.is_null()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: investigate possible memory leak on `init` (owned pointer)
|
|
||||||
#[doc = "Creates a new vector of [`" $prefix "_" $name "_t`].
|
|
||||||
|
|
||||||
# Example
|
|
||||||
|
|
||||||
See the [`" $prefix "_" $name "_vec_t`] type to get an example."]
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe extern "C" fn [<$prefix _ $name _vec_new>](out: *mut [<$prefix _ $name _vec_t>], length: usize, init: *mut [<$prefix _ $name _t>]) {
|
|
||||||
let mut bytes: Vec<[<$prefix _ $name _t>]> = Vec::with_capacity(length);
|
|
||||||
|
|
||||||
for i in 0..length {
|
|
||||||
bytes.push(::std::ptr::read(init.add(i)));
|
|
||||||
}
|
|
||||||
|
|
||||||
let pointer = bytes.as_mut_ptr();
|
|
||||||
debug_assert!(bytes.len() == bytes.capacity());
|
|
||||||
|
|
||||||
(*out).data = pointer;
|
|
||||||
(*out).size = length;
|
|
||||||
::std::mem::forget(bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[doc = "Creates a new uninitialized vector of [`" $prefix "_" $name "_t`].
|
|
||||||
|
|
||||||
# Example
|
|
||||||
|
|
||||||
```rust
|
|
||||||
# use inline_c::assert_c;
|
|
||||||
# fn main() {
|
|
||||||
# (assert_c! {
|
|
||||||
# #include \"tests/wasmer.h\"
|
|
||||||
#
|
|
||||||
int main() {
|
|
||||||
// Creates an empty vector of `" $prefix "_" $name "_t`.
|
|
||||||
" $prefix "_" $name "_vec_t vector;
|
|
||||||
" $prefix "_" $name "_vec_new_uninitialized(&vector, 3);
|
|
||||||
|
|
||||||
// Check that it contains 3 items.
|
|
||||||
assert(vector.size == 3);
|
|
||||||
|
|
||||||
// Free it.
|
|
||||||
" $prefix "_" $name "_vec_delete(&vector);
|
|
||||||
}
|
|
||||||
# })
|
|
||||||
# .success();
|
|
||||||
# }
|
|
||||||
```"]
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe extern "C" fn [<$prefix _ $name _vec_new_uninitialized>](out: *mut [<$prefix _ $name _vec_t>], length: usize) {
|
|
||||||
let mut bytes: Vec<[<$prefix _ $name _t>]> = Vec::with_capacity(length);
|
|
||||||
let pointer = bytes.as_mut_ptr();
|
|
||||||
|
|
||||||
(*out).data = pointer;
|
|
||||||
(*out).size = length;
|
|
||||||
|
|
||||||
::std::mem::forget(bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[doc = "Performs a deep copy of a vector of [`" $prefix "_" $name "_t`]."]
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe extern "C" fn [<$prefix _ $name _vec_copy>](
|
|
||||||
out_ptr: &mut [<$prefix _ $name _vec_t>],
|
|
||||||
in_ptr: & [<wasm _$name _vec_t>])
|
|
||||||
{
|
|
||||||
*out_ptr = in_ptr.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[doc = "Deletes a vector of [`" $prefix "_" $name "_t`].
|
|
||||||
|
|
||||||
# Example
|
|
||||||
|
|
||||||
See the [`" $prefix "_" $name "_vec_t`] type to get an example."]
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe extern "C" fn [<$prefix _ $name _vec_delete>](ptr: Option<&mut [<$prefix _ $name _vec_t>]>) {
|
|
||||||
if let Some(vec) = ptr {
|
|
||||||
if !vec.data.is_null() {
|
|
||||||
Vec::from_raw_parts(vec.data, vec.size, vec.size);
|
|
||||||
vec.data = ::std::ptr::null_mut();
|
|
||||||
vec.size = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wasm_declare_vec_inner!($name, $prefix);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! wasm_declare_boxed_vec {
|
macro_rules! wasm_declare_boxed_vec {
|
||||||
($name:ident) => {
|
($name:ident) => {
|
||||||
wasm_declare_boxed_vec!($name, wasm);
|
wasm_declare_boxed_vec!($name, wasm);
|
||||||
@@ -269,223 +242,60 @@ macro_rules! wasm_declare_boxed_vec {
|
|||||||
|
|
||||||
($name:ident, $prefix:ident) => {
|
($name:ident, $prefix:ident) => {
|
||||||
paste::paste! {
|
paste::paste! {
|
||||||
#[doc = "Represents a vector of `" $prefix "_" $name "_t`.
|
wasm_declare_vec_inner!(
|
||||||
|
name: [<$prefix _ $name _vec_t>],
|
||||||
Read the documentation of [`" $prefix "_" $name "_t`] to see more concrete examples."]
|
ty: Option<Box<[<$prefix _ $name _t>]>>,
|
||||||
#[derive(Debug)]
|
c_ty: stringify!([<$prefix _ $name _t>] *),
|
||||||
#[repr(C)]
|
c_val: "NULL",
|
||||||
pub struct [<$prefix _ $name _vec_t>] {
|
new: [<$prefix _ $name _vec_new>],
|
||||||
pub size: usize,
|
empty: [<$prefix _ $name _vec_new_empty>],
|
||||||
pub data: *mut *mut [<$prefix _ $name _t>],
|
uninit: [<$prefix _ $name _vec_new_uninitialized>],
|
||||||
}
|
copy: [<$prefix _ $name _vec_copy>],
|
||||||
|
delete: [<$prefix _ $name _vec_delete>],
|
||||||
impl Clone for [<$prefix _ $name _vec_t>] {
|
);
|
||||||
fn clone(&self) -> Self {
|
|
||||||
if self.data.is_null() {
|
|
||||||
return Self {
|
|
||||||
size: self.size,
|
|
||||||
data: ::std::ptr::null_mut(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
let data =
|
|
||||||
unsafe {
|
|
||||||
let data: *mut Option<Box<[<$prefix _ $name _t>]>> = self.data as _;
|
|
||||||
let vec = Vec::from_raw_parts(data, self.size, self.size);
|
|
||||||
let mut vec_copy = vec.clone().into_boxed_slice();
|
|
||||||
let new_ptr = vec_copy.as_mut_ptr() as *mut *mut [<$prefix _ $name _t>];
|
|
||||||
|
|
||||||
::std::mem::forget(vec);
|
|
||||||
::std::mem::forget(vec_copy);
|
|
||||||
|
|
||||||
new_ptr
|
|
||||||
};
|
|
||||||
|
|
||||||
Self {
|
|
||||||
size: self.size,
|
|
||||||
data,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> From<Vec<Box<[<$prefix _ $name _t>]>>> for [<$prefix _ $name _vec_t>] {
|
|
||||||
fn from(other: Vec<Box<[<$prefix _ $name _t>]>>) -> Self {
|
|
||||||
let boxed_slice: Box<[Box<[<$prefix _ $name _t>]>]> = other.into_boxed_slice();
|
|
||||||
let mut boxed_slice: Box<[*mut [<$prefix _ $name _t>]]> = unsafe { ::std::mem::transmute(boxed_slice) };
|
|
||||||
let size = boxed_slice.len();
|
|
||||||
let data = boxed_slice.as_mut_ptr();
|
|
||||||
|
|
||||||
::std::mem::forget(boxed_slice);
|
|
||||||
Self {
|
|
||||||
size,
|
|
||||||
data,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T: Into<[<$prefix _ $name _t>]> + Clone> From<&'a [T]> for [<$prefix _ $name _vec_t>] {
|
|
||||||
fn from(other: &'a [T]) -> Self {
|
|
||||||
let size = other.len();
|
|
||||||
let mut copied_data = other
|
|
||||||
.iter()
|
|
||||||
.cloned()
|
|
||||||
.map(Into::into)
|
|
||||||
.map(Box::new)
|
|
||||||
.map(Box::into_raw)
|
|
||||||
.collect::<Vec<*mut [<$prefix _ $name _t>]>>()
|
|
||||||
.into_boxed_slice();
|
|
||||||
let data = copied_data.as_mut_ptr();
|
|
||||||
::std::mem::forget(copied_data);
|
|
||||||
|
|
||||||
Self {
|
|
||||||
size,
|
|
||||||
data,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: do this properly
|
|
||||||
impl [<$prefix _ $name _vec_t>] {
|
|
||||||
pub unsafe fn into_slice(&self) -> Option<&[Box<[<$prefix _ $name _t>]>]>{
|
|
||||||
if self.data.is_null() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let slice: &[*mut [<$prefix _ $name _t>]] = ::std::slice::from_raw_parts(self.data, self.size);
|
|
||||||
let slice: &[Box<[<$prefix _ $name _t>]>] = ::std::mem::transmute(slice);
|
|
||||||
Some(slice)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: investigate possible memory leak on `init` (owned pointer)
|
|
||||||
#[doc = "Creates a new vector of [`" $prefix "_" $name "_t`]."]
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe extern "C" fn [<$prefix _ $name _vec_new>](out: *mut [<$prefix _ $name _vec_t>], length: usize, init: *const *mut [<$prefix _ $name _t>]) {
|
|
||||||
let mut bytes: Vec<*mut [<$prefix _ $name _t>]> = Vec::with_capacity(length);
|
|
||||||
|
|
||||||
for i in 0..length {
|
|
||||||
bytes.push(*init.add(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut boxed_vec = bytes.into_boxed_slice();
|
|
||||||
let pointer = boxed_vec.as_mut_ptr();
|
|
||||||
|
|
||||||
(*out).data = pointer;
|
|
||||||
(*out).size = length;
|
|
||||||
|
|
||||||
::std::mem::forget(boxed_vec);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[doc = "Creates a new uninitialized vector of [`" $prefix "_" $name "_t`].
|
|
||||||
|
|
||||||
# Example
|
|
||||||
|
|
||||||
```rust
|
|
||||||
# use inline_c::assert_c;
|
|
||||||
# fn main() {
|
|
||||||
# (assert_c! {
|
|
||||||
# #include \"tests/wasmer.h\"
|
|
||||||
#
|
|
||||||
int main() {
|
|
||||||
// Creates an empty vector of `" $prefix "_" $name "_t`.
|
|
||||||
" $prefix "_" $name "_vec_t vector;
|
|
||||||
" $prefix "_" $name "_vec_new_uninitialized(&vector, 3);
|
|
||||||
|
|
||||||
// Check that it contains 3 items.
|
|
||||||
assert(vector.size == 3);
|
|
||||||
|
|
||||||
// Free it.
|
|
||||||
" $prefix "_" $name "_vec_delete(&vector);
|
|
||||||
}
|
|
||||||
# })
|
|
||||||
# .success();
|
|
||||||
# }
|
|
||||||
```"]
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe extern "C" fn [<$prefix _ $name _vec_new_uninitialized>](out: *mut [<$prefix _ $name _vec_t>], length: usize) {
|
|
||||||
let mut bytes: Vec<*mut [<$prefix _ $name _t>]> = vec![::std::ptr::null_mut(); length];
|
|
||||||
let pointer = bytes.as_mut_ptr();
|
|
||||||
|
|
||||||
(*out).data = pointer;
|
|
||||||
(*out).size = length;
|
|
||||||
|
|
||||||
::std::mem::forget(bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[doc = "Performs a deep copy of a vector of [`" $prefix "_" $name "_t`]."]
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe extern "C" fn [<$prefix _ $name _vec_copy>](
|
|
||||||
out_ptr: &mut [<$prefix _ $name _vec_t>],
|
|
||||||
in_ptr: & [<$prefix _ $name _vec_t>])
|
|
||||||
{
|
|
||||||
*out_ptr = in_ptr.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[doc = "Deletes a vector of [`" $prefix "_" $name "_t`].
|
|
||||||
|
|
||||||
# Example
|
|
||||||
|
|
||||||
See the [`" $prefix "_" $name "_vec_t`] type to get an example."]
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe extern "C" fn [<$prefix _ $name _vec_delete>](ptr: Option<&mut [<$prefix _ $name _vec_t>]>) {
|
|
||||||
if let Some(vec) = ptr {
|
|
||||||
if !vec.data.is_null() {
|
|
||||||
let data = vec.data as *mut Option<Box<[<$prefix _ $name _t>]>>;
|
|
||||||
let _data: Vec<Option<Box<[<$prefix _ $name _t>]>>> = Vec::from_raw_parts(data, vec.size, vec.size);
|
|
||||||
|
|
||||||
vec.data = ::std::ptr::null_mut();
|
|
||||||
vec.size = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
wasm_declare_vec_inner!($name, $prefix);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! wasm_declare_ref_base {
|
|
||||||
($name:ident) => {
|
|
||||||
wasm_declare_ref_base!($name, wasm);
|
|
||||||
};
|
|
||||||
|
|
||||||
($name:ident, $prefix:ident) => {
|
|
||||||
wasm_declare_own!($name, $prefix);
|
|
||||||
|
|
||||||
paste::paste! {
|
|
||||||
#[no_mangle]
|
|
||||||
pub extern "C" fn [<$prefix _ $name _copy>](_arg: *const [<$prefix _ $name _t>]) -> *mut [<$prefix _ $name _t>] {
|
|
||||||
todo!("in generated declare ref base");
|
|
||||||
//ptr::null_mut()
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: finish this...
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
macro_rules! wasm_impl_copy {
|
||||||
#[macro_export]
|
|
||||||
macro_rules! wasm_declare_own {
|
|
||||||
($name:ident) => {
|
($name:ident) => {
|
||||||
wasm_declare_own!($name, $prefix);
|
wasm_impl_copy!($name, wasm);
|
||||||
};
|
};
|
||||||
|
|
||||||
($name:ident, $prefix:ident) => {
|
($name:ident, $prefix:ident) => {
|
||||||
paste::paste! {
|
paste::paste! {
|
||||||
#[repr(C)]
|
|
||||||
pub struct [<$prefix _ $name _t>] {}
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn [<$prefix _ $name _delete>](_arg: *mut [<$prefix _ $name _t>]) {
|
pub extern "C" fn [<$prefix _ $name _copy>](src: Option<&[<$prefix _ $name _t>]>) -> Option<Box<[<$prefix _ $name _t>]>> {
|
||||||
todo!("in generated delete")
|
Some(Box::new(src?.clone()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
macro_rules! wasm_impl_delete {
|
||||||
|
($name:ident) => {
|
||||||
|
wasm_impl_delete!($name, wasm);
|
||||||
|
};
|
||||||
|
|
||||||
|
($name:ident, $prefix:ident) => {
|
||||||
|
paste::paste! {
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn [<$prefix _ $name _delete>](_: Option<Box<[<$prefix _ $name _t>]>>) {}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! wasm_impl_copy_delete {
|
||||||
|
($name:ident) => {
|
||||||
|
wasm_impl_copy_delete!($name, wasm);
|
||||||
|
};
|
||||||
|
|
||||||
|
($name:ident, $prefix:ident) => {
|
||||||
|
wasm_impl_copy!($name, $prefix);
|
||||||
|
wasm_impl_delete!($name, $prefix);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! c_try {
|
macro_rules! c_try {
|
||||||
($expr:expr; otherwise $return:expr) => {{
|
($expr:expr; otherwise $return:expr) => {{
|
||||||
let res: Result<_, _> = $expr;
|
let res: Result<_, _> = $expr;
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
/// Private Rust macros.
|
/// Private Rust macros.
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
pub mod macros;
|
mod macros;
|
||||||
|
|
||||||
/// An engine drives the compilation and the runtime.
|
/// An engine drives the compilation and the runtime.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
use super::store::wasm_store_t;
|
use super::store::wasm_store_t;
|
||||||
use super::types::{
|
use super::types::{wasm_byte_vec_t, wasm_exporttype_vec_t, wasm_importtype_vec_t};
|
||||||
wasm_byte_vec_t, wasm_exporttype_t, wasm_exporttype_vec_t, wasm_importtype_t,
|
use crate::error::update_last_error;
|
||||||
wasm_importtype_vec_t,
|
|
||||||
};
|
|
||||||
use crate::error::{update_last_error, CApiError};
|
|
||||||
use std::ptr::NonNull;
|
use std::ptr::NonNull;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use wasmer_api::Module;
|
use wasmer_api::Module;
|
||||||
@@ -36,8 +33,7 @@ pub unsafe extern "C" fn wasm_module_new(
|
|||||||
let store = store?;
|
let store = store?;
|
||||||
let bytes = bytes?;
|
let bytes = bytes?;
|
||||||
|
|
||||||
let bytes = bytes.into_slice()?;
|
let module = c_try!(Module::from_binary(&store.inner, bytes.as_slice()));
|
||||||
let module = c_try!(Module::from_binary(&store.inner, bytes));
|
|
||||||
|
|
||||||
Some(Box::new(wasm_module_t {
|
Some(Box::new(wasm_module_t {
|
||||||
inner: Arc::new(module),
|
inner: Arc::new(module),
|
||||||
@@ -107,12 +103,7 @@ pub unsafe extern "C" fn wasm_module_validate(
|
|||||||
None => return false,
|
None => return false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let bytes = match bytes.into_slice() {
|
if let Err(error) = Module::validate(&store.inner, bytes.as_slice()) {
|
||||||
Some(bytes) => bytes,
|
|
||||||
None => return false,
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Err(error) = Module::validate(&store.inner, bytes) {
|
|
||||||
update_last_error(error);
|
update_last_error(error);
|
||||||
|
|
||||||
false
|
false
|
||||||
@@ -238,11 +229,10 @@ pub unsafe extern "C" fn wasm_module_exports(
|
|||||||
let exports = module
|
let exports = module
|
||||||
.inner
|
.inner
|
||||||
.exports()
|
.exports()
|
||||||
.map(Into::into)
|
.map(|export| Some(Box::new(export.into())))
|
||||||
.map(Box::new)
|
.collect();
|
||||||
.collect::<Vec<Box<wasm_exporttype_t>>>();
|
|
||||||
|
|
||||||
*out = exports.into();
|
out.set_buffer(exports);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an array of the imported types in the module.
|
/// Returns an array of the imported types in the module.
|
||||||
@@ -379,11 +369,10 @@ pub unsafe extern "C" fn wasm_module_imports(
|
|||||||
let imports = module
|
let imports = module
|
||||||
.inner
|
.inner
|
||||||
.imports()
|
.imports()
|
||||||
.map(Into::into)
|
.map(|import| Some(Box::new(import.into())))
|
||||||
.map(Box::new)
|
.collect();
|
||||||
.collect::<Vec<Box<wasm_importtype_t>>>();
|
|
||||||
|
|
||||||
*out = imports.into();
|
out.set_buffer(imports);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deserializes a serialized module binary into a `wasm_module_t`.
|
/// Deserializes a serialized module binary into a `wasm_module_t`.
|
||||||
@@ -472,21 +461,11 @@ pub unsafe extern "C" fn wasm_module_imports(
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasm_module_deserialize(
|
pub unsafe extern "C" fn wasm_module_deserialize(
|
||||||
store: &wasm_store_t,
|
store: &wasm_store_t,
|
||||||
bytes: *const wasm_byte_vec_t,
|
bytes: Option<&wasm_byte_vec_t>,
|
||||||
) -> Option<NonNull<wasm_module_t>> {
|
) -> Option<NonNull<wasm_module_t>> {
|
||||||
// TODO: read config from store and use that to decide which compiler to use
|
let bytes = bytes?;
|
||||||
|
|
||||||
let byte_slice = if bytes.is_null() || (&*bytes).into_slice().is_none() {
|
let module = c_try!(Module::deserialize(&store.inner, bytes.as_slice()));
|
||||||
update_last_error(CApiError {
|
|
||||||
msg: "`bytes` is null or represents an empty slice".to_string(),
|
|
||||||
});
|
|
||||||
|
|
||||||
return None;
|
|
||||||
} else {
|
|
||||||
(&*bytes).into_slice().unwrap()
|
|
||||||
};
|
|
||||||
|
|
||||||
let module = c_try!(Module::deserialize(&store.inner, byte_slice));
|
|
||||||
|
|
||||||
Some(NonNull::new_unchecked(Box::into_raw(Box::new(
|
Some(NonNull::new_unchecked(Box::into_raw(Box::new(
|
||||||
wasm_module_t {
|
wasm_module_t {
|
||||||
@@ -503,10 +482,7 @@ pub unsafe extern "C" fn wasm_module_deserialize(
|
|||||||
///
|
///
|
||||||
/// See [`wasm_module_deserialize`].
|
/// See [`wasm_module_deserialize`].
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasm_module_serialize(
|
pub unsafe extern "C" fn wasm_module_serialize(module: &wasm_module_t, out: &mut wasm_byte_vec_t) {
|
||||||
module: &wasm_module_t,
|
|
||||||
out_ptr: &mut wasm_byte_vec_t,
|
|
||||||
) {
|
|
||||||
let byte_vec = match module.inner.serialize() {
|
let byte_vec = match module.inner.serialize() {
|
||||||
Ok(byte_vec) => byte_vec,
|
Ok(byte_vec) => byte_vec,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
@@ -514,7 +490,7 @@ pub unsafe extern "C" fn wasm_module_serialize(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
*out_ptr = byte_vec.into();
|
out.set_buffer(byte_vec);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ pub unsafe extern "C" fn wasm_trap_new(
|
|||||||
_store: &mut wasm_store_t,
|
_store: &mut wasm_store_t,
|
||||||
message: &wasm_message_t,
|
message: &wasm_message_t,
|
||||||
) -> Option<Box<wasm_trap_t>> {
|
) -> Option<Box<wasm_trap_t>> {
|
||||||
let message_bytes = message.into_slice()?;
|
let message_bytes = message.as_slice();
|
||||||
|
|
||||||
// The trap message is typed with `wasm_message_t` which is a
|
// The trap message is typed with `wasm_message_t` which is a
|
||||||
// typeref to `wasm_name_t` with the exception that it's a
|
// typeref to `wasm_name_t` with the exception that it's a
|
||||||
@@ -117,10 +117,7 @@ pub unsafe extern "C" fn wasm_trap_message(
|
|||||||
let mut byte_vec = message.into_bytes();
|
let mut byte_vec = message.into_bytes();
|
||||||
byte_vec.push(0);
|
byte_vec.push(0);
|
||||||
|
|
||||||
let byte_vec: wasm_byte_vec_t = byte_vec.into();
|
out.set_buffer(byte_vec);
|
||||||
|
|
||||||
out.size = byte_vec.size;
|
|
||||||
out.data = byte_vec.data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the origin frame attached to the trap.
|
/// Gets the origin frame attached to the trap.
|
||||||
@@ -137,10 +134,12 @@ pub unsafe extern "C" fn wasm_trap_trace(
|
|||||||
out: &mut wasm_frame_vec_t,
|
out: &mut wasm_frame_vec_t,
|
||||||
) {
|
) {
|
||||||
let frames = trap.inner.trace();
|
let frames = trap.inner.trace();
|
||||||
let frame_vec: wasm_frame_vec_t = frames.into();
|
out.set_buffer(
|
||||||
|
frames
|
||||||
out.size = frame_vec.size;
|
.iter()
|
||||||
out.data = frame_vec.data;
|
.map(|frame| Some(Box::new(frame.into())))
|
||||||
|
.collect(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -1,40 +1,37 @@
|
|||||||
use super::{owned_wasm_name_t, wasm_externtype_t, wasm_name_t};
|
use super::{wasm_externtype_t, wasm_name_t};
|
||||||
use wasmer_api::ExportType;
|
use wasmer_api::ExportType;
|
||||||
|
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct wasm_exporttype_t {
|
pub struct wasm_exporttype_t {
|
||||||
name: owned_wasm_name_t,
|
name: wasm_name_t,
|
||||||
extern_type: Box<wasm_externtype_t>,
|
extern_type: wasm_externtype_t,
|
||||||
}
|
}
|
||||||
|
|
||||||
wasm_declare_boxed_vec!(exporttype);
|
wasm_declare_boxed_vec!(exporttype);
|
||||||
|
wasm_impl_copy_delete!(exporttype);
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wasm_exporttype_new(
|
pub extern "C" fn wasm_exporttype_new(
|
||||||
name: Option<&wasm_name_t>,
|
name: &wasm_name_t,
|
||||||
extern_type: Option<Box<wasm_externtype_t>>,
|
extern_type: Box<wasm_externtype_t>,
|
||||||
) -> Option<Box<wasm_exporttype_t>> {
|
) -> Box<wasm_exporttype_t> {
|
||||||
let name = unsafe { owned_wasm_name_t::new(name?) };
|
Box::new(wasm_exporttype_t {
|
||||||
Some(Box::new(wasm_exporttype_t {
|
name: name.clone(),
|
||||||
name,
|
extern_type: *extern_type,
|
||||||
extern_type: extern_type?,
|
})
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wasm_exporttype_name(export_type: &wasm_exporttype_t) -> &wasm_name_t {
|
pub extern "C" fn wasm_exporttype_name(export_type: &wasm_exporttype_t) -> &wasm_name_t {
|
||||||
export_type.name.as_ref()
|
&export_type.name
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wasm_exporttype_type(export_type: &wasm_exporttype_t) -> &wasm_externtype_t {
|
pub extern "C" fn wasm_exporttype_type(export_type: &wasm_exporttype_t) -> &wasm_externtype_t {
|
||||||
export_type.extern_type.as_ref()
|
&export_type.extern_type
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub extern "C" fn wasm_exporttype_delete(_export_type: Option<Box<wasm_exporttype_t>>) {}
|
|
||||||
|
|
||||||
impl From<ExportType> for wasm_exporttype_t {
|
impl From<ExportType> for wasm_exporttype_t {
|
||||||
fn from(other: ExportType) -> Self {
|
fn from(other: ExportType) -> Self {
|
||||||
(&other).into()
|
(&other).into()
|
||||||
@@ -43,8 +40,8 @@ impl From<ExportType> for wasm_exporttype_t {
|
|||||||
|
|
||||||
impl From<&ExportType> for wasm_exporttype_t {
|
impl From<&ExportType> for wasm_exporttype_t {
|
||||||
fn from(other: &ExportType) -> Self {
|
fn from(other: &ExportType) -> Self {
|
||||||
let name: owned_wasm_name_t = other.name().to_string().into();
|
let name: wasm_name_t = other.name().to_string().into();
|
||||||
let extern_type: Box<wasm_externtype_t> = Box::new(other.ty().into());
|
let extern_type: wasm_externtype_t = other.ty().into();
|
||||||
|
|
||||||
wasm_exporttype_t { name, extern_type }
|
wasm_exporttype_t { name, extern_type }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,30 @@
|
|||||||
use super::{wasm_externtype_t, wasm_valtype_vec_delete, wasm_valtype_vec_t, WasmExternType};
|
use super::{wasm_externtype_t, wasm_valtype_vec_t, WasmExternType};
|
||||||
|
use std::fmt;
|
||||||
use wasmer_api::{ExternType, FunctionType, ValType};
|
use wasmer_api::{ExternType, FunctionType, ValType};
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub(crate) struct WasmFunctionType {
|
pub(crate) struct WasmFunctionType {
|
||||||
pub(crate) function_type: FunctionType,
|
pub(crate) function_type: FunctionType,
|
||||||
params: Box<wasm_valtype_vec_t>,
|
params: wasm_valtype_vec_t,
|
||||||
results: Box<wasm_valtype_vec_t>,
|
results: wasm_valtype_vec_t,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WasmFunctionType {
|
impl WasmFunctionType {
|
||||||
pub(crate) fn new(function_type: FunctionType) -> Self {
|
pub(crate) fn new(function_type: FunctionType) -> Self {
|
||||||
let params: Box<wasm_valtype_vec_t> = Box::new(function_type.params().into());
|
let params: Vec<_> = function_type
|
||||||
let results: Box<wasm_valtype_vec_t> = Box::new(function_type.results().into());
|
.params()
|
||||||
|
.iter()
|
||||||
|
.map(|&valtype| Some(Box::new(valtype.into())))
|
||||||
|
.collect();
|
||||||
|
let results: Vec<_> = function_type
|
||||||
|
.results()
|
||||||
|
.iter()
|
||||||
|
.map(|&valtype| Some(Box::new(valtype.into())))
|
||||||
|
.collect();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
function_type,
|
function_type,
|
||||||
params,
|
params: params.into(),
|
||||||
results,
|
results: results.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -27,6 +35,12 @@ impl Clone for WasmFunctionType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for WasmFunctionType {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
self.function_type.fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
@@ -52,6 +66,7 @@ impl wasm_functype_t {
|
|||||||
}
|
}
|
||||||
|
|
||||||
wasm_declare_boxed_vec!(functype);
|
wasm_declare_boxed_vec!(functype);
|
||||||
|
wasm_impl_copy_delete!(functype);
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasm_functype_new(
|
pub unsafe extern "C" fn wasm_functype_new(
|
||||||
@@ -62,44 +77,29 @@ pub unsafe extern "C" fn wasm_functype_new(
|
|||||||
let results = results?;
|
let results = results?;
|
||||||
|
|
||||||
let params_as_valtype: Vec<ValType> = params
|
let params_as_valtype: Vec<ValType> = params
|
||||||
.into_slice()?
|
.take()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|val| val.as_ref().into())
|
.map(|val| val.as_ref().unwrap().as_ref().into())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
let results_as_valtype: Vec<ValType> = results
|
let results_as_valtype: Vec<ValType> = results
|
||||||
.into_slice()?
|
.take()
|
||||||
.iter()
|
.into_iter()
|
||||||
.map(|val| val.as_ref().into())
|
.map(|val| val.as_ref().unwrap().as_ref().into())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
wasm_valtype_vec_delete(Some(params));
|
|
||||||
wasm_valtype_vec_delete(Some(results));
|
|
||||||
|
|
||||||
Some(Box::new(wasm_functype_t::new(FunctionType::new(
|
Some(Box::new(wasm_functype_t::new(FunctionType::new(
|
||||||
params_as_valtype,
|
params_as_valtype,
|
||||||
results_as_valtype,
|
results_as_valtype,
|
||||||
))))
|
))))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe extern "C" fn wasm_functype_delete(_function_type: Option<Box<wasm_functype_t>>) {}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe extern "C" fn wasm_functype_copy(
|
|
||||||
function_type: Option<&wasm_functype_t>,
|
|
||||||
) -> Option<Box<wasm_functype_t>> {
|
|
||||||
let function_type = function_type?;
|
|
||||||
|
|
||||||
Some(Box::new(function_type.clone()))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasm_functype_params(
|
pub unsafe extern "C" fn wasm_functype_params(
|
||||||
function_type: Option<&wasm_functype_t>,
|
function_type: Option<&wasm_functype_t>,
|
||||||
) -> Option<&wasm_valtype_vec_t> {
|
) -> Option<&wasm_valtype_vec_t> {
|
||||||
let function_type = function_type?;
|
let function_type = function_type?;
|
||||||
|
|
||||||
Some(function_type.inner().params.as_ref())
|
Some(&function_type.inner().params)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@@ -108,5 +108,5 @@ pub unsafe extern "C" fn wasm_functype_results(
|
|||||||
) -> Option<&wasm_valtype_vec_t> {
|
) -> Option<&wasm_valtype_vec_t> {
|
||||||
let function_type = function_type?;
|
let function_type = function_type?;
|
||||||
|
|
||||||
Some(function_type.inner().results.as_ref())
|
Some(&function_type.inner().results)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,12 +8,12 @@ use wasmer_api::{ExternType, GlobalType};
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct WasmGlobalType {
|
pub(crate) struct WasmGlobalType {
|
||||||
pub(crate) global_type: GlobalType,
|
pub(crate) global_type: GlobalType,
|
||||||
content: Box<wasm_valtype_t>,
|
content: wasm_valtype_t,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WasmGlobalType {
|
impl WasmGlobalType {
|
||||||
pub(crate) fn new(global_type: GlobalType) -> Self {
|
pub(crate) fn new(global_type: GlobalType) -> Self {
|
||||||
let content = Box::new(global_type.ty.into());
|
let content = global_type.ty.into();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
global_type,
|
global_type,
|
||||||
@@ -79,5 +79,5 @@ pub unsafe extern "C" fn wasm_globaltype_mutability(
|
|||||||
pub unsafe extern "C" fn wasm_globaltype_content(
|
pub unsafe extern "C" fn wasm_globaltype_content(
|
||||||
global_type: &wasm_globaltype_t,
|
global_type: &wasm_globaltype_t,
|
||||||
) -> &wasm_valtype_t {
|
) -> &wasm_valtype_t {
|
||||||
global_type.inner().content.as_ref()
|
&global_type.inner().content
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,49 +1,43 @@
|
|||||||
use super::{owned_wasm_name_t, wasm_externtype_t, wasm_name_t};
|
use super::{wasm_externtype_t, wasm_name_t};
|
||||||
use wasmer_api::ImportType;
|
use wasmer_api::ImportType;
|
||||||
|
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct wasm_importtype_t {
|
pub struct wasm_importtype_t {
|
||||||
module: owned_wasm_name_t,
|
module: wasm_name_t,
|
||||||
name: owned_wasm_name_t,
|
name: wasm_name_t,
|
||||||
extern_type: Box<wasm_externtype_t>,
|
extern_type: wasm_externtype_t,
|
||||||
}
|
}
|
||||||
|
|
||||||
wasm_declare_boxed_vec!(importtype);
|
wasm_declare_boxed_vec!(importtype);
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wasm_importtype_new(
|
pub extern "C" fn wasm_importtype_new(
|
||||||
module: Option<&wasm_name_t>,
|
module: Option<Box<wasm_name_t>>,
|
||||||
name: Option<&wasm_name_t>,
|
name: Option<Box<wasm_name_t>>,
|
||||||
extern_type: Option<Box<wasm_externtype_t>>,
|
extern_type: Option<Box<wasm_externtype_t>>,
|
||||||
) -> Option<Box<wasm_importtype_t>> {
|
) -> Option<Box<wasm_importtype_t>> {
|
||||||
let (module, name) = unsafe {
|
|
||||||
(
|
|
||||||
owned_wasm_name_t::new(module?),
|
|
||||||
owned_wasm_name_t::new(name?),
|
|
||||||
)
|
|
||||||
};
|
|
||||||
Some(Box::new(wasm_importtype_t {
|
Some(Box::new(wasm_importtype_t {
|
||||||
name,
|
name: *name?,
|
||||||
module,
|
module: *module?,
|
||||||
extern_type: extern_type?,
|
extern_type: *extern_type?,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wasm_importtype_module(import_type: &wasm_importtype_t) -> &wasm_name_t {
|
pub extern "C" fn wasm_importtype_module(import_type: &wasm_importtype_t) -> &wasm_name_t {
|
||||||
import_type.module.as_ref()
|
&import_type.module
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wasm_importtype_name(import_type: &wasm_importtype_t) -> &wasm_name_t {
|
pub extern "C" fn wasm_importtype_name(import_type: &wasm_importtype_t) -> &wasm_name_t {
|
||||||
import_type.name.as_ref()
|
&import_type.name
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wasm_importtype_type(import_type: &wasm_importtype_t) -> &wasm_externtype_t {
|
pub extern "C" fn wasm_importtype_type(import_type: &wasm_importtype_t) -> &wasm_externtype_t {
|
||||||
import_type.extern_type.as_ref()
|
&import_type.extern_type
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@@ -57,9 +51,9 @@ impl From<ImportType> for wasm_importtype_t {
|
|||||||
|
|
||||||
impl From<&ImportType> for wasm_importtype_t {
|
impl From<&ImportType> for wasm_importtype_t {
|
||||||
fn from(other: &ImportType) -> Self {
|
fn from(other: &ImportType) -> Self {
|
||||||
let module: owned_wasm_name_t = other.module().to_string().into();
|
let module: wasm_name_t = other.module().to_string().into();
|
||||||
let name: owned_wasm_name_t = other.name().to_string().into();
|
let name: wasm_name_t = other.name().to_string().into();
|
||||||
let extern_type: Box<wasm_externtype_t> = Box::new(other.ty().into());
|
let extern_type: wasm_externtype_t = other.ty().into();
|
||||||
|
|
||||||
wasm_importtype_t {
|
wasm_importtype_t {
|
||||||
module,
|
module,
|
||||||
|
|||||||
@@ -4,18 +4,18 @@ use wasmer_api::{ExternType, MemoryType, Pages};
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct WasmMemoryType {
|
pub(crate) struct WasmMemoryType {
|
||||||
pub(crate) memory_type: MemoryType,
|
pub(crate) memory_type: MemoryType,
|
||||||
limits: Box<wasm_limits_t>,
|
limits: wasm_limits_t,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WasmMemoryType {
|
impl WasmMemoryType {
|
||||||
pub(crate) fn new(memory_type: MemoryType) -> Self {
|
pub(crate) fn new(memory_type: MemoryType) -> Self {
|
||||||
let limits = Box::new(wasm_limits_t {
|
let limits = wasm_limits_t {
|
||||||
min: memory_type.minimum.0 as _,
|
min: memory_type.minimum.0 as _,
|
||||||
max: memory_type
|
max: memory_type
|
||||||
.maximum
|
.maximum
|
||||||
.map(|max| max.0 as _)
|
.map(|max| max.0 as _)
|
||||||
.unwrap_or(LIMITS_MAX_SENTINEL),
|
.unwrap_or(LIMITS_MAX_SENTINEL),
|
||||||
});
|
};
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
memory_type,
|
memory_type,
|
||||||
@@ -79,5 +79,5 @@ const LIMITS_MAX_SENTINEL: u32 = u32::max_value();
|
|||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasm_memorytype_limits(memory_type: &wasm_memorytype_t) -> &wasm_limits_t {
|
pub unsafe extern "C" fn wasm_memorytype_limits(memory_type: &wasm_memorytype_t) -> &wasm_limits_t {
|
||||||
memory_type.inner().limits.as_ref()
|
&memory_type.inner().limits
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,63 +28,9 @@ wasm_declare_vec!(byte);
|
|||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
pub type wasm_name_t = wasm_byte_vec_t;
|
pub type wasm_name_t = wasm_byte_vec_t;
|
||||||
|
|
||||||
impl AsRef<wasm_name_t> for wasm_name_t {
|
impl From<String> for wasm_name_t {
|
||||||
fn as_ref(&self) -> &wasm_name_t {
|
|
||||||
&self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An owned version of `wasm_name_t`.
|
|
||||||
///
|
|
||||||
/// Assumes that data is either valid host-owned or null.
|
|
||||||
// NOTE: `wasm_name_t` already does a deep copy, so we just derive `Clone` here.
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
#[repr(transparent)]
|
|
||||||
#[allow(non_camel_case_types)]
|
|
||||||
pub struct owned_wasm_name_t(wasm_name_t);
|
|
||||||
|
|
||||||
impl owned_wasm_name_t {
|
|
||||||
/// Take ownership of some `wasm_name_t`
|
|
||||||
///
|
|
||||||
/// # Safety
|
|
||||||
/// You must ensure that the data pointed to by `wasm_name_t` is valid and
|
|
||||||
/// that it is not owned by anyone else.
|
|
||||||
pub unsafe fn new(name: &wasm_name_t) -> Self {
|
|
||||||
Self(wasm_name_t {
|
|
||||||
size: name.size,
|
|
||||||
data: name.data,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for owned_wasm_name_t {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
if !self.0.data.is_null() {
|
|
||||||
let _v = unsafe { Vec::from_raw_parts(self.0.data, self.0.size, self.0.size) };
|
|
||||||
self.0.data = std::ptr::null_mut();
|
|
||||||
self.0.size = 0;
|
|
||||||
}
|
|
||||||
// why can't we call this function?
|
|
||||||
//unsafe { crate::wasm_c_api::macros::wasm_byte_vec_delete(Some(self.0)) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsRef<wasm_name_t> for owned_wasm_name_t {
|
|
||||||
fn as_ref(&self) -> &wasm_name_t {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<String> for owned_wasm_name_t {
|
|
||||||
fn from(string: String) -> Self {
|
fn from(string: String) -> Self {
|
||||||
let mut boxed_str: Box<str> = string.into_boxed_str();
|
string.into_bytes().into()
|
||||||
let data = boxed_str.as_mut_ptr();
|
|
||||||
let size = boxed_str.bytes().len();
|
|
||||||
let wasm_name = wasm_name_t { data, size };
|
|
||||||
|
|
||||||
Box::leak(boxed_str);
|
|
||||||
|
|
||||||
Self(wasm_name)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,21 +10,21 @@ const LIMITS_MAX_SENTINEL: u32 = u32::max_value();
|
|||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct WasmTableType {
|
pub(crate) struct WasmTableType {
|
||||||
pub(crate) table_type: TableType,
|
pub(crate) _table_type: TableType,
|
||||||
limits: Box<wasm_limits_t>,
|
limits: wasm_limits_t,
|
||||||
content: Box<wasm_valtype_t>,
|
content: wasm_valtype_t,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WasmTableType {
|
impl WasmTableType {
|
||||||
pub(crate) fn new(table_type: TableType) -> Self {
|
pub(crate) fn new(table_type: TableType) -> Self {
|
||||||
let limits = Box::new(wasm_limits_t {
|
let limits = wasm_limits_t {
|
||||||
min: table_type.minimum as _,
|
min: table_type.minimum as _,
|
||||||
max: table_type.maximum.unwrap_or(LIMITS_MAX_SENTINEL),
|
max: table_type.maximum.unwrap_or(LIMITS_MAX_SENTINEL),
|
||||||
});
|
};
|
||||||
let content = Box::new(table_type.ty.into());
|
let content = table_type.ty.into();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
table_type,
|
_table_type: table_type,
|
||||||
limits,
|
limits,
|
||||||
content,
|
content,
|
||||||
}
|
}
|
||||||
@@ -79,12 +79,12 @@ pub unsafe extern "C" fn wasm_tabletype_new(
|
|||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasm_tabletype_limits(table_type: &wasm_tabletype_t) -> &wasm_limits_t {
|
pub unsafe extern "C" fn wasm_tabletype_limits(table_type: &wasm_tabletype_t) -> &wasm_limits_t {
|
||||||
table_type.inner().limits.as_ref()
|
&table_type.inner().limits
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasm_tabletype_element(table_type: &wasm_tabletype_t) -> &wasm_valtype_t {
|
pub unsafe extern "C" fn wasm_tabletype_element(table_type: &wasm_tabletype_t) -> &wasm_valtype_t {
|
||||||
table_type.inner().content.as_ref()
|
&table_type.inner().content
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ pub unsafe extern "C" fn wasmer_module_name(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
*out = name.as_bytes().to_vec().into();
|
out.set_buffer(name.as_bytes().to_vec());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unstable non-standard Wasmer-specific API to set the module's
|
/// Unstable non-standard Wasmer-specific API to set the module's
|
||||||
@@ -144,12 +144,9 @@ pub unsafe extern "C" fn wasmer_module_set_name(
|
|||||||
// own
|
// own
|
||||||
name: &wasm_name_t,
|
name: &wasm_name_t,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let name = match name.into_slice() {
|
let name = match str::from_utf8(name.as_slice()) {
|
||||||
Some(name) => match str::from_utf8(name) {
|
Ok(name) => name,
|
||||||
Ok(name) => name,
|
Err(_) => return false, // not ideal!
|
||||||
Err(_) => return false, // not ideal!
|
|
||||||
},
|
|
||||||
None => return false,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
match Arc::get_mut(&mut module.inner) {
|
match Arc::get_mut(&mut module.inner) {
|
||||||
|
|||||||
@@ -54,7 +54,6 @@
|
|||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
use super::super::types::wasm_name_t;
|
use super::super::types::wasm_name_t;
|
||||||
use crate::error::CApiError;
|
|
||||||
use enumset::EnumSet;
|
use enumset::EnumSet;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
use std::str::{self, FromStr};
|
use std::str::{self, FromStr};
|
||||||
@@ -153,7 +152,7 @@ pub unsafe extern "C" fn wasmer_triple_new(
|
|||||||
)));
|
)));
|
||||||
|
|
||||||
Some(Box::new(wasmer_triple_t {
|
Some(Box::new(wasmer_triple_t {
|
||||||
inner: c_try!(Triple::from_str(triple).map_err(|e| CApiError { msg: e.to_string() })),
|
inner: c_try!(Triple::from_str(triple)),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,13 +2,9 @@
|
|||||||
//! API.
|
//! API.
|
||||||
|
|
||||||
use super::super::{
|
use super::super::{
|
||||||
externals::wasm_extern_t,
|
externals::wasm_extern_t, module::wasm_module_t, store::wasm_store_t, types::wasm_name_t,
|
||||||
module::wasm_module_t,
|
|
||||||
store::wasm_store_t,
|
|
||||||
types::{owned_wasm_name_t, wasm_name_t},
|
|
||||||
wasi::wasi_env_t,
|
wasi::wasi_env_t,
|
||||||
};
|
};
|
||||||
use crate::error::CApiError;
|
|
||||||
use wasmer_api::Extern;
|
use wasmer_api::Extern;
|
||||||
use wasmer_wasi::{generate_import_object_from_env, get_wasi_version};
|
use wasmer_wasi::{generate_import_object_from_env, get_wasi_version};
|
||||||
|
|
||||||
@@ -22,8 +18,8 @@ use wasmer_wasi::{generate_import_object_from_env, get_wasi_version};
|
|||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct wasmer_named_extern_t {
|
pub struct wasmer_named_extern_t {
|
||||||
module: owned_wasm_name_t,
|
module: wasm_name_t,
|
||||||
name: owned_wasm_name_t,
|
name: wasm_name_t,
|
||||||
r#extern: Box<wasm_extern_t>,
|
r#extern: Box<wasm_extern_t>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,7 +117,7 @@ mod __cbindgen_hack__ {
|
|||||||
pub extern "C" fn wasmer_named_extern_module(
|
pub extern "C" fn wasmer_named_extern_module(
|
||||||
named_extern: Option<&wasmer_named_extern_t>,
|
named_extern: Option<&wasmer_named_extern_t>,
|
||||||
) -> Option<&wasm_name_t> {
|
) -> Option<&wasm_name_t> {
|
||||||
Some(named_extern?.module.as_ref())
|
Some(&named_extern?.module)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Non-standard function to get the name of a `wasmer_named_extern_t`.
|
/// Non-standard function to get the name of a `wasmer_named_extern_t`.
|
||||||
@@ -131,7 +127,7 @@ pub extern "C" fn wasmer_named_extern_module(
|
|||||||
pub extern "C" fn wasmer_named_extern_name(
|
pub extern "C" fn wasmer_named_extern_name(
|
||||||
named_extern: Option<&wasmer_named_extern_t>,
|
named_extern: Option<&wasmer_named_extern_t>,
|
||||||
) -> Option<&wasm_name_t> {
|
) -> Option<&wasm_name_t> {
|
||||||
Some(named_extern?.name.as_ref())
|
Some(&named_extern?.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Non-standard function to get the wrapped extern of a
|
/// Non-standard function to get the wrapped extern of a
|
||||||
@@ -171,29 +167,27 @@ fn wasi_get_unordered_imports_inner(
|
|||||||
|
|
||||||
let store = &store.inner;
|
let store = &store.inner;
|
||||||
|
|
||||||
let version = c_try!(
|
let version = c_try!(get_wasi_version(&module.inner, false)
|
||||||
get_wasi_version(&module.inner, false).ok_or_else(|| CApiError {
|
.ok_or("could not detect a WASI version on the given module"));
|
||||||
msg: "could not detect a WASI version on the given module".to_string(),
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
let import_object = generate_import_object_from_env(store, wasi_env.inner.clone(), version);
|
let import_object = generate_import_object_from_env(store, wasi_env.inner.clone(), version);
|
||||||
|
|
||||||
*imports = import_object
|
imports.set_buffer(
|
||||||
.into_iter()
|
import_object
|
||||||
.map(|((module, name), export)| {
|
.into_iter()
|
||||||
let module = module.into();
|
.map(|((module, name), export)| {
|
||||||
let name = name.into();
|
let module = module.into();
|
||||||
let extern_inner = Extern::from_vm_export(store, export);
|
let name = name.into();
|
||||||
|
let extern_inner = Extern::from_vm_export(store, export);
|
||||||
|
|
||||||
Box::new(wasmer_named_extern_t {
|
Some(Box::new(wasmer_named_extern_t {
|
||||||
module,
|
module,
|
||||||
name,
|
name,
|
||||||
r#extern: Box::new(extern_inner.into()),
|
r#extern: Box::new(extern_inner.into()),
|
||||||
|
}))
|
||||||
})
|
})
|
||||||
})
|
.collect::<Vec<_>>(),
|
||||||
.collect::<Vec<_>>()
|
);
|
||||||
.into();
|
|
||||||
|
|
||||||
Some(())
|
Some(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use super::types::{wasm_ref_t, wasm_valkind_enum};
|
use super::types::{wasm_ref_t, wasm_valkind_enum};
|
||||||
use crate::error::{update_last_error, CApiError};
|
use crate::error::update_last_error;
|
||||||
use std::convert::{TryFrom, TryInto};
|
use std::convert::{TryFrom, TryInto};
|
||||||
use wasmer_api::Val;
|
use wasmer_api::Val;
|
||||||
|
|
||||||
@@ -121,6 +121,15 @@ impl Clone for wasm_val_t {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for wasm_val_t {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
kind: wasm_valkind_enum::WASM_I64 as _,
|
||||||
|
of: wasm_val_inner { int64_t: 0 },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasm_val_copy(
|
pub unsafe extern "C" fn wasm_val_copy(
|
||||||
// own
|
// own
|
||||||
@@ -147,7 +156,7 @@ pub unsafe extern "C" fn wasm_val_copy(
|
|||||||
},
|
},
|
||||||
|
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
update_last_error(CApiError { msg: e.to_string() });
|
update_last_error(e);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use super::{
|
|||||||
module::wasm_module_t,
|
module::wasm_module_t,
|
||||||
store::wasm_store_t,
|
store::wasm_store_t,
|
||||||
};
|
};
|
||||||
use crate::error::{update_last_error, CApiError};
|
use crate::error::update_last_error;
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
@@ -212,9 +212,7 @@ pub unsafe extern "C" fn wasi_env_read_stdout(
|
|||||||
if let Some(stdout) = stdout.as_mut() {
|
if let Some(stdout) = stdout.as_mut() {
|
||||||
stdout
|
stdout
|
||||||
} else {
|
} else {
|
||||||
update_last_error(CApiError {
|
update_last_error("could not find a file handle for `stdout`");
|
||||||
msg: "could not find a file handle for `stdout`".to_string(),
|
|
||||||
});
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -235,15 +233,11 @@ pub unsafe extern "C" fn wasi_env_read_stderr(
|
|||||||
if let Some(stderr) = stderr.as_mut() {
|
if let Some(stderr) = stderr.as_mut() {
|
||||||
stderr
|
stderr
|
||||||
} else {
|
} else {
|
||||||
update_last_error(CApiError {
|
update_last_error("could not find a file handle for `stderr`");
|
||||||
msg: "could not find a file handle for `stderr`".to_string(),
|
|
||||||
});
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
update_last_error(CApiError {
|
update_last_error("could not find a file handle for `stderr`");
|
||||||
msg: "could not find a file handle for `stderr`".to_string(),
|
|
||||||
});
|
|
||||||
return -1;
|
return -1;
|
||||||
};
|
};
|
||||||
read_inner(stderr, inner_buffer)
|
read_inner(stderr, inner_buffer)
|
||||||
@@ -348,33 +342,29 @@ fn wasi_get_imports_inner(
|
|||||||
|
|
||||||
let store = &store.inner;
|
let store = &store.inner;
|
||||||
|
|
||||||
let version = c_try!(
|
let version = c_try!(get_wasi_version(&module.inner, false)
|
||||||
get_wasi_version(&module.inner, false).ok_or_else(|| CApiError {
|
.ok_or("could not detect a WASI version on the given module"));
|
||||||
msg: "could not detect a WASI version on the given module".to_string(),
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
let import_object = generate_import_object_from_env(store, wasi_env.inner.clone(), version);
|
let import_object = generate_import_object_from_env(store, wasi_env.inner.clone(), version);
|
||||||
|
|
||||||
*imports = module
|
imports.set_buffer(c_try!(module
|
||||||
.inner
|
.inner
|
||||||
.imports()
|
.imports()
|
||||||
.map(|import_type| {
|
.map(|import_type| {
|
||||||
let export = c_try!(import_object
|
let export = import_object
|
||||||
.resolve_by_name(import_type.module(), import_type.name())
|
.resolve_by_name(import_type.module(), import_type.name())
|
||||||
.ok_or_else(|| CApiError {
|
.ok_or_else(|| {
|
||||||
msg: format!(
|
format!(
|
||||||
"Failed to resolve import \"{}\" \"{}\"",
|
"Failed to resolve import \"{}\" \"{}\"",
|
||||||
import_type.module(),
|
import_type.module(),
|
||||||
import_type.name()
|
import_type.name()
|
||||||
),
|
)
|
||||||
}));
|
})?;
|
||||||
let inner = Extern::from_vm_export(store, export);
|
let inner = Extern::from_vm_export(store, export);
|
||||||
|
|
||||||
Some(Box::new(inner.into()))
|
Ok(Some(Box::new(inner.into())))
|
||||||
})
|
})
|
||||||
.collect::<Option<Vec<_>>>()?
|
.collect::<Result<Vec<_>, String>>()));
|
||||||
.into();
|
|
||||||
|
|
||||||
Some(())
|
Some(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,16 +11,8 @@ use super::types::wasm_byte_vec_t;
|
|||||||
#[cfg(feature = "wat")]
|
#[cfg(feature = "wat")]
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wat2wasm(wat: &wasm_byte_vec_t, out: &mut wasm_byte_vec_t) {
|
pub unsafe extern "C" fn wat2wasm(wat: &wasm_byte_vec_t, out: &mut wasm_byte_vec_t) {
|
||||||
let wat: &[u8] = match wat.into_slice() {
|
match wasmer_api::wat2wasm(wat.as_slice()) {
|
||||||
Some(v) => v,
|
Ok(val) => out.set_buffer(val.into_owned()),
|
||||||
_ => {
|
|
||||||
out.data = std::ptr::null_mut();
|
|
||||||
out.size = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let result: wasm_byte_vec_t = match wasmer_api::wat2wasm(wat) {
|
|
||||||
Ok(val) => val.into_owned().into(),
|
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
crate::error::update_last_error(err);
|
crate::error::update_last_error(err);
|
||||||
out.data = std::ptr::null_mut();
|
out.data = std::ptr::null_mut();
|
||||||
@@ -28,8 +20,6 @@ pub unsafe extern "C" fn wat2wasm(wat: &wasm_byte_vec_t, out: &mut wasm_byte_vec
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
*out = result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -25,9 +25,9 @@ more-asserts = "0.2"
|
|||||||
gimli = { version = "0.25", optional = true }
|
gimli = { version = "0.25", optional = true }
|
||||||
smallvec = "1.6"
|
smallvec = "1.6"
|
||||||
loupe = "0.1"
|
loupe = "0.1"
|
||||||
|
target-lexicon = { version = "0.12.2", default-features = false }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
target-lexicon = { version = "0.12.2", default-features = false }
|
|
||||||
cranelift-codegen = { version = "0.76", features = ["all-arch"] }
|
cranelift-codegen = { version = "0.76", features = ["all-arch"] }
|
||||||
lazy_static = "1.4"
|
lazy_static = "1.4"
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ use gimli::write::{Address, EhFrame, FrameTable};
|
|||||||
use loupe::MemoryUsage;
|
use loupe::MemoryUsage;
|
||||||
use rayon::prelude::{IntoParallelRefIterator, ParallelIterator};
|
use rayon::prelude::{IntoParallelRefIterator, ParallelIterator};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use target_lexicon::{Architecture, OperatingSystem};
|
||||||
use wasmer_compiler::CompileError;
|
use wasmer_compiler::CompileError;
|
||||||
use wasmer_compiler::{CallingConvention, ModuleTranslationState, Target};
|
use wasmer_compiler::{CallingConvention, ModuleTranslationState, Target};
|
||||||
use wasmer_compiler::{
|
use wasmer_compiler::{
|
||||||
@@ -29,14 +30,12 @@ use wasmer_compiler::{
|
|||||||
FunctionBodyData, MiddlewareBinaryReader, ModuleMiddleware, ModuleMiddlewareChain,
|
FunctionBodyData, MiddlewareBinaryReader, ModuleMiddleware, ModuleMiddlewareChain,
|
||||||
SectionIndex,
|
SectionIndex,
|
||||||
};
|
};
|
||||||
#[cfg(all(target_arch = "x86_64", target_os = "linux"))]
|
|
||||||
use wasmer_compiler::{
|
use wasmer_compiler::{
|
||||||
CustomSection, CustomSectionProtection, Relocation, RelocationKind, RelocationTarget,
|
CustomSection, CustomSectionProtection, Relocation, RelocationKind, RelocationTarget,
|
||||||
SectionBody,
|
SectionBody,
|
||||||
};
|
};
|
||||||
use wasmer_types::entity::{EntityRef, PrimaryMap};
|
use wasmer_types::entity::{EntityRef, PrimaryMap};
|
||||||
use wasmer_types::{FunctionIndex, LocalFunctionIndex, SignatureIndex};
|
use wasmer_types::{FunctionIndex, LocalFunctionIndex, SignatureIndex};
|
||||||
#[cfg(all(target_arch = "x86_64", target_os = "linux"))]
|
|
||||||
use wasmer_vm::libcalls::LibCall;
|
use wasmer_vm::libcalls::LibCall;
|
||||||
|
|
||||||
/// A compiler that compiles a WebAssembly module with Cranelift, translating the Wasm to Cranelift IR,
|
/// A compiler that compiles a WebAssembly module with Cranelift, translating the Wasm to Cranelift IR,
|
||||||
@@ -92,14 +91,13 @@ impl Compiler for CraneliftCompiler {
|
|||||||
// FDEs will cause some issues in Linux.
|
// FDEs will cause some issues in Linux.
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
use std::sync::Mutex;
|
|
||||||
match target.triple().default_calling_convention() {
|
match target.triple().default_calling_convention() {
|
||||||
Ok(CallingConvention::SystemV) => {
|
Ok(CallingConvention::SystemV) => {
|
||||||
match isa.create_systemv_cie() {
|
match isa.create_systemv_cie() {
|
||||||
Some(cie) => {
|
Some(cie) => {
|
||||||
let mut dwarf_frametable = FrameTable::default();
|
let mut dwarf_frametable = FrameTable::default();
|
||||||
let cie_id = dwarf_frametable.add_cie(cie);
|
let cie_id = dwarf_frametable.add_cie(cie);
|
||||||
Some((Arc::new(Mutex::new(dwarf_frametable)), cie_id))
|
Some((dwarf_frametable, cie_id))
|
||||||
}
|
}
|
||||||
// Even though we are in a SystemV system, Cranelift doesn't support it
|
// Even though we are in a SystemV system, Cranelift doesn't support it
|
||||||
None => None,
|
None => None,
|
||||||
@@ -111,30 +109,36 @@ impl Compiler for CraneliftCompiler {
|
|||||||
|
|
||||||
let mut custom_sections = PrimaryMap::new();
|
let mut custom_sections = PrimaryMap::new();
|
||||||
|
|
||||||
#[cfg(all(target_arch = "x86_64", target_os = "linux"))]
|
let probestack_trampoline_relocation_target = if target.triple().operating_system
|
||||||
let probestack_trampoline = CustomSection {
|
== OperatingSystem::Linux
|
||||||
protection: CustomSectionProtection::ReadExecute,
|
&& target.triple().architecture == Architecture::X86_64
|
||||||
// We create a jump to an absolute 64bits address
|
{
|
||||||
// with an indrect jump immediatly followed but the absolute address
|
let probestack_trampoline = CustomSection {
|
||||||
// JMP [IP+0] FF 25 00 00 00 00
|
protection: CustomSectionProtection::ReadExecute,
|
||||||
// 64bits ADDR 00 00 00 00 00 00 00 00 preset to 0 until the relocation takes place
|
// We create a jump to an absolute 64bits address
|
||||||
bytes: SectionBody::new_with_vec(vec![
|
// with an indrect jump immediatly followed but the absolute address
|
||||||
0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
// JMP [IP+0] FF 25 00 00 00 00
|
||||||
]),
|
// 64bits ADDR 00 00 00 00 00 00 00 00 preset to 0 until the relocation takes place
|
||||||
relocations: vec![Relocation {
|
bytes: SectionBody::new_with_vec(vec![
|
||||||
kind: RelocationKind::Abs8,
|
0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
reloc_target: RelocationTarget::LibCall(LibCall::Probestack),
|
0x00,
|
||||||
// 6 is the size of the jmp instruction. The relocated address must follow
|
]),
|
||||||
offset: 6,
|
relocations: vec![Relocation {
|
||||||
addend: 0,
|
kind: RelocationKind::Abs8,
|
||||||
}],
|
reloc_target: RelocationTarget::LibCall(LibCall::Probestack),
|
||||||
};
|
// 6 is the size of the jmp instruction. The relocated address must follow
|
||||||
#[cfg(all(target_arch = "x86_64", target_os = "linux"))]
|
offset: 6,
|
||||||
custom_sections.push(probestack_trampoline);
|
addend: 0,
|
||||||
#[cfg(all(target_arch = "x86_64", target_os = "linux"))]
|
}],
|
||||||
let probestack_trampoline_relocation_target = SectionIndex::new(custom_sections.len() - 1);
|
};
|
||||||
|
custom_sections.push(probestack_trampoline);
|
||||||
|
|
||||||
let functions = function_body_inputs
|
Some(SectionIndex::new(custom_sections.len() - 1))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let (functions, fdes): (Vec<CompiledFunction>, Vec<_>) = function_body_inputs
|
||||||
.iter()
|
.iter()
|
||||||
.collect::<Vec<(LocalFunctionIndex, &FunctionBodyData<'_>)>>()
|
.collect::<Vec<(LocalFunctionIndex, &FunctionBodyData<'_>)>>()
|
||||||
.par_iter()
|
.par_iter()
|
||||||
@@ -170,12 +174,8 @@ impl Compiler for CraneliftCompiler {
|
|||||||
)?;
|
)?;
|
||||||
|
|
||||||
let mut code_buf: Vec<u8> = Vec::new();
|
let mut code_buf: Vec<u8> = Vec::new();
|
||||||
let mut reloc_sink = RelocSink::new(
|
let mut reloc_sink =
|
||||||
&module,
|
RelocSink::new(&module, func_index, probestack_trampoline_relocation_target);
|
||||||
func_index,
|
|
||||||
#[cfg(all(target_arch = "x86_64", target_os = "linux"))]
|
|
||||||
probestack_trampoline_relocation_target,
|
|
||||||
);
|
|
||||||
let mut trap_sink = TrapSink::new();
|
let mut trap_sink = TrapSink::new();
|
||||||
let mut stackmap_sink = binemit::NullStackMapSink {};
|
let mut stackmap_sink = binemit::NullStackMapSink {};
|
||||||
context
|
context
|
||||||
@@ -190,31 +190,31 @@ impl Compiler for CraneliftCompiler {
|
|||||||
CompileError::Codegen(pretty_error(&context.func, Some(&*isa), error))
|
CompileError::Codegen(pretty_error(&context.func, Some(&*isa), error))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let unwind_info = match compiled_function_unwind_info(&*isa, &context)? {
|
let (unwind_info, fde) = match compiled_function_unwind_info(&*isa, &context)? {
|
||||||
#[cfg(feature = "unwind")]
|
#[cfg(feature = "unwind")]
|
||||||
CraneliftUnwindInfo::FDE(fde) => {
|
CraneliftUnwindInfo::FDE(fde) => {
|
||||||
if let Some((dwarf_frametable, cie_id)) = &dwarf_frametable {
|
if dwarf_frametable.is_some() {
|
||||||
dwarf_frametable
|
let fde = fde.to_fde(Address::Symbol {
|
||||||
.lock()
|
// The symbol is the kind of relocation.
|
||||||
.expect("Can't write into DWARF frametable")
|
// "0" is used for functions
|
||||||
.add_fde(
|
symbol: WriterRelocate::FUNCTION_SYMBOL,
|
||||||
*cie_id,
|
// We use the addend as a way to specify the
|
||||||
fde.to_fde(Address::Symbol {
|
// function index
|
||||||
// The symbol is the kind of relocation.
|
addend: i.index() as _,
|
||||||
// "0" is used for functions
|
});
|
||||||
symbol: WriterRelocate::FUNCTION_SYMBOL,
|
|
||||||
// We use the addend as a way to specify the
|
|
||||||
// function index
|
|
||||||
addend: i.index() as _,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
// The unwind information is inserted into the dwarf section
|
// The unwind information is inserted into the dwarf section
|
||||||
Some(CompiledFunctionUnwindInfo::Dwarf)
|
(Some(CompiledFunctionUnwindInfo::Dwarf), Some(fde))
|
||||||
} else {
|
} else {
|
||||||
None
|
(None, None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
other => other.maybe_into_to_windows_unwind(),
|
#[cfg(feature = "unwind")]
|
||||||
|
other => (other.maybe_into_to_windows_unwind(), None),
|
||||||
|
|
||||||
|
// This is a bit hacky, but necessary since gimli is not
|
||||||
|
// available when the "unwind" feature is disabled.
|
||||||
|
#[cfg(not(feature = "unwind"))]
|
||||||
|
other => (other.maybe_into_to_windows_unwind(), None::<()>),
|
||||||
};
|
};
|
||||||
|
|
||||||
let range = reader.range();
|
let range = reader.range();
|
||||||
@@ -223,40 +223,41 @@ impl Compiler for CraneliftCompiler {
|
|||||||
// We transform the Cranelift JumpTable's into compiler JumpTables
|
// We transform the Cranelift JumpTable's into compiler JumpTables
|
||||||
let func_jt_offsets = transform_jump_table(context.func.jt_offsets);
|
let func_jt_offsets = transform_jump_table(context.func.jt_offsets);
|
||||||
|
|
||||||
Ok(CompiledFunction {
|
Ok((
|
||||||
body: FunctionBody {
|
CompiledFunction {
|
||||||
body: code_buf,
|
body: FunctionBody {
|
||||||
unwind_info,
|
body: code_buf,
|
||||||
|
unwind_info,
|
||||||
|
},
|
||||||
|
jt_offsets: func_jt_offsets,
|
||||||
|
relocations: reloc_sink.func_relocs,
|
||||||
|
frame_info: CompiledFunctionFrameInfo {
|
||||||
|
address_map,
|
||||||
|
traps: trap_sink.traps,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
jt_offsets: func_jt_offsets,
|
fde,
|
||||||
relocations: reloc_sink.func_relocs,
|
))
|
||||||
frame_info: CompiledFunctionFrameInfo {
|
|
||||||
address_map,
|
|
||||||
traps: trap_sink.traps,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<_>, CompileError>>()?
|
.collect::<Result<Vec<_>, CompileError>>()?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect::<PrimaryMap<LocalFunctionIndex, _>>();
|
.unzip();
|
||||||
|
|
||||||
#[cfg(feature = "unwind")]
|
#[cfg(feature = "unwind")]
|
||||||
let dwarf = {
|
let dwarf = if let Some((mut dwarf_frametable, cie_id)) = dwarf_frametable {
|
||||||
let dwarf = if let Some((dwarf_frametable, _cie_id)) = dwarf_frametable {
|
for fde in fdes {
|
||||||
let mut eh_frame = EhFrame(WriterRelocate::new(target.triple().endianness().ok()));
|
if let Some(fde) = fde {
|
||||||
dwarf_frametable
|
dwarf_frametable.add_fde(cie_id, fde);
|
||||||
.lock()
|
}
|
||||||
.unwrap()
|
}
|
||||||
.write_eh_frame(&mut eh_frame)
|
let mut eh_frame = EhFrame(WriterRelocate::new(target.triple().endianness().ok()));
|
||||||
.unwrap();
|
dwarf_frametable.write_eh_frame(&mut eh_frame).unwrap();
|
||||||
|
|
||||||
let eh_frame_section = eh_frame.0.into_section();
|
let eh_frame_section = eh_frame.0.into_section();
|
||||||
custom_sections.push(eh_frame_section);
|
custom_sections.push(eh_frame_section);
|
||||||
Some(Dwarf::new(SectionIndex::new(custom_sections.len() - 1)))
|
Some(Dwarf::new(SectionIndex::new(custom_sections.len() - 1)))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
|
||||||
dwarf
|
|
||||||
};
|
};
|
||||||
#[cfg(not(feature = "unwind"))]
|
#[cfg(not(feature = "unwind"))]
|
||||||
let dwarf = None;
|
let dwarf = None;
|
||||||
@@ -289,7 +290,7 @@ impl Compiler for CraneliftCompiler {
|
|||||||
.collect::<PrimaryMap<FunctionIndex, FunctionBody>>();
|
.collect::<PrimaryMap<FunctionIndex, FunctionBody>>();
|
||||||
|
|
||||||
Ok(Compilation::new(
|
Ok(Compilation::new(
|
||||||
functions,
|
functions.into_iter().collect(),
|
||||||
custom_sections,
|
custom_sections,
|
||||||
function_call_trampolines,
|
function_call_trampolines,
|
||||||
dynamic_function_trampolines,
|
dynamic_function_trampolines,
|
||||||
|
|||||||
@@ -2,12 +2,10 @@
|
|||||||
|
|
||||||
use crate::translator::{irlibcall_to_libcall, irreloc_to_relocationkind};
|
use crate::translator::{irlibcall_to_libcall, irreloc_to_relocationkind};
|
||||||
use cranelift_codegen::binemit;
|
use cranelift_codegen::binemit;
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
use cranelift_codegen::ir::LibCall;
|
use cranelift_codegen::ir::LibCall;
|
||||||
use cranelift_codegen::ir::{self, ExternalName};
|
use cranelift_codegen::ir::{self, ExternalName};
|
||||||
use cranelift_entity::EntityRef as CraneliftEntityRef;
|
use cranelift_entity::EntityRef as CraneliftEntityRef;
|
||||||
use wasmer_compiler::{JumpTable, Relocation, RelocationTarget, TrapInformation};
|
use wasmer_compiler::{JumpTable, Relocation, RelocationTarget, TrapInformation};
|
||||||
#[cfg(all(target_arch = "x86_64", target_os = "linux"))]
|
|
||||||
use wasmer_compiler::{RelocationKind, SectionIndex};
|
use wasmer_compiler::{RelocationKind, SectionIndex};
|
||||||
use wasmer_types::entity::EntityRef;
|
use wasmer_types::entity::EntityRef;
|
||||||
use wasmer_types::{FunctionIndex, LocalFunctionIndex, ModuleInfo};
|
use wasmer_types::{FunctionIndex, LocalFunctionIndex, ModuleInfo};
|
||||||
@@ -24,8 +22,7 @@ pub(crate) struct RelocSink<'a> {
|
|||||||
pub func_relocs: Vec<Relocation>,
|
pub func_relocs: Vec<Relocation>,
|
||||||
|
|
||||||
/// The section where the probestack trampoline call is located
|
/// The section where the probestack trampoline call is located
|
||||||
#[cfg(all(target_arch = "x86_64", target_os = "linux"))]
|
pub probestack_trampoline_relocation_target: Option<SectionIndex>,
|
||||||
pub probestack_trampoline_relocation_target: SectionIndex,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> binemit::RelocSink for RelocSink<'a> {
|
impl<'a> binemit::RelocSink for RelocSink<'a> {
|
||||||
@@ -45,13 +42,12 @@ impl<'a> binemit::RelocSink for RelocSink<'a> {
|
|||||||
.expect("The provided function should be local"),
|
.expect("The provided function should be local"),
|
||||||
)
|
)
|
||||||
} else if let ExternalName::LibCall(libcall) = *name {
|
} else if let ExternalName::LibCall(libcall) = *name {
|
||||||
match libcall {
|
match (libcall, self.probestack_trampoline_relocation_target) {
|
||||||
#[cfg(all(target_arch = "x86_64", target_os = "linux"))]
|
(LibCall::Probestack, Some(probestack_trampoline_relocation_target)) => {
|
||||||
LibCall::Probestack => {
|
|
||||||
self.func_relocs.push(Relocation {
|
self.func_relocs.push(Relocation {
|
||||||
kind: RelocationKind::X86CallPCRel4,
|
kind: RelocationKind::X86CallPCRel4,
|
||||||
reloc_target: RelocationTarget::CustomSection(
|
reloc_target: RelocationTarget::CustomSection(
|
||||||
self.probestack_trampoline_relocation_target,
|
probestack_trampoline_relocation_target,
|
||||||
),
|
),
|
||||||
offset: offset,
|
offset: offset,
|
||||||
addend: addend,
|
addend: addend,
|
||||||
@@ -100,8 +96,7 @@ impl<'a> RelocSink<'a> {
|
|||||||
pub fn new(
|
pub fn new(
|
||||||
module: &'a ModuleInfo,
|
module: &'a ModuleInfo,
|
||||||
func_index: FunctionIndex,
|
func_index: FunctionIndex,
|
||||||
#[cfg(all(target_arch = "x86_64", target_os = "linux"))]
|
probestack_trampoline_relocation_target: Option<SectionIndex>,
|
||||||
probestack_trampoline_relocation_target: SectionIndex,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let local_func_index = module
|
let local_func_index = module
|
||||||
.local_func_index(func_index)
|
.local_func_index(func_index)
|
||||||
@@ -110,7 +105,6 @@ impl<'a> RelocSink<'a> {
|
|||||||
module,
|
module,
|
||||||
local_func_index,
|
local_func_index,
|
||||||
func_relocs: Vec::new(),
|
func_relocs: Vec::new(),
|
||||||
#[cfg(all(target_arch = "x86_64", target_os = "linux"))]
|
|
||||||
probestack_trampoline_relocation_target,
|
probestack_trampoline_relocation_target,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ loupe = "0.1"
|
|||||||
package = "inkwell"
|
package = "inkwell"
|
||||||
version = "0.1.0-beta.4"
|
version = "0.1.0-beta.4"
|
||||||
default-features = false
|
default-features = false
|
||||||
features = ["llvm11-0", "target-x86", "target-aarch64"]
|
features = ["llvm12-0", "target-x86", "target-aarch64"]
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
cc = "1.0"
|
cc = "1.0"
|
||||||
|
|||||||
@@ -24,14 +24,14 @@ to native speeds.
|
|||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
The LLVM compiler requires a valid installation of LLVM in your system.
|
The LLVM compiler requires a valid installation of LLVM in your system.
|
||||||
It currently requires **LLVM 11**.
|
It currently requires **LLVM 12**.
|
||||||
|
|
||||||
|
|
||||||
You can install LLVM easily on your Debian-like system via this command:
|
You can install LLVM easily on your Debian-like system via this command:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
wget https://apt.llvm.org/llvm.sh -O /tmp/llvm.sh
|
wget https://apt.llvm.org/llvm.sh -O /tmp/llvm.sh
|
||||||
sudo bash /tmp/llvm.sh 11
|
sudo bash /tmp/llvm.sh 12
|
||||||
```
|
```
|
||||||
|
|
||||||
Or in macOS:
|
Or in macOS:
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use inkwell::{
|
|||||||
attributes::{Attribute, AttributeLoc},
|
attributes::{Attribute, AttributeLoc},
|
||||||
builder::Builder,
|
builder::Builder,
|
||||||
context::Context,
|
context::Context,
|
||||||
types::{BasicMetadataTypeEnum, BasicType, FunctionType, StructType},
|
types::{AnyType, BasicMetadataTypeEnum, BasicType, FunctionType, StructType},
|
||||||
values::{BasicValue, BasicValueEnum, CallSiteValue, FunctionValue, IntValue, PointerValue},
|
values::{BasicValue, BasicValueEnum, CallSiteValue, FunctionValue, IntValue, PointerValue},
|
||||||
AddressSpace,
|
AddressSpace,
|
||||||
};
|
};
|
||||||
@@ -206,17 +206,16 @@ impl Abi for Aarch64SystemV {
|
|||||||
.map(|&ty| type_to_llvm(intrinsics, ty))
|
.map(|&ty| type_to_llvm(intrinsics, ty))
|
||||||
.collect::<Result<_, _>>()?;
|
.collect::<Result<_, _>>()?;
|
||||||
|
|
||||||
let sret = context
|
let sret = context.struct_type(&basic_types, false);
|
||||||
.struct_type(&basic_types, false)
|
let sret_ptr = sret.ptr_type(AddressSpace::Generic);
|
||||||
.ptr_type(AddressSpace::Generic);
|
|
||||||
|
|
||||||
let param_types =
|
let param_types =
|
||||||
std::iter::once(Ok(sret.as_basic_type_enum())).chain(param_types);
|
std::iter::once(Ok(sret_ptr.as_basic_type_enum())).chain(param_types);
|
||||||
|
|
||||||
let mut attributes = vec![(
|
let mut attributes = vec![(
|
||||||
context.create_enum_attribute(
|
context.create_type_attribute(
|
||||||
Attribute::get_named_enum_kind_id("sret"),
|
Attribute::get_named_enum_kind_id("sret"),
|
||||||
0,
|
sret.as_any_type_enum(),
|
||||||
),
|
),
|
||||||
AttributeLoc::Param(0),
|
AttributeLoc::Param(0),
|
||||||
)];
|
)];
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use inkwell::{
|
|||||||
attributes::{Attribute, AttributeLoc},
|
attributes::{Attribute, AttributeLoc},
|
||||||
builder::Builder,
|
builder::Builder,
|
||||||
context::Context,
|
context::Context,
|
||||||
types::{BasicMetadataTypeEnum, BasicType, FunctionType, StructType},
|
types::{AnyType, BasicMetadataTypeEnum, BasicType, FunctionType, StructType},
|
||||||
values::{
|
values::{
|
||||||
BasicValue, BasicValueEnum, CallSiteValue, FloatValue, FunctionValue, IntValue,
|
BasicValue, BasicValueEnum, CallSiteValue, FloatValue, FunctionValue, IntValue,
|
||||||
PointerValue, VectorValue,
|
PointerValue, VectorValue,
|
||||||
@@ -263,14 +263,17 @@ impl Abi for X86_64SystemV {
|
|||||||
.map(|&ty| type_to_llvm(intrinsics, ty))
|
.map(|&ty| type_to_llvm(intrinsics, ty))
|
||||||
.collect::<Result<_, _>>()?;
|
.collect::<Result<_, _>>()?;
|
||||||
|
|
||||||
let sret = context
|
let sret = context.struct_type(&basic_types, false);
|
||||||
.struct_type(&basic_types, false)
|
let sret_ptr = sret.ptr_type(AddressSpace::Generic);
|
||||||
.ptr_type(AddressSpace::Generic);
|
|
||||||
|
|
||||||
let param_types = std::iter::once(Ok(sret.as_basic_type_enum())).chain(param_types);
|
let param_types =
|
||||||
|
std::iter::once(Ok(sret_ptr.as_basic_type_enum())).chain(param_types);
|
||||||
|
|
||||||
let mut attributes = vec![(
|
let mut attributes = vec![(
|
||||||
context.create_enum_attribute(Attribute::get_named_enum_kind_id("sret"), 0),
|
context.create_type_attribute(
|
||||||
|
Attribute::get_named_enum_kind_id("sret"),
|
||||||
|
sret.as_any_type_enum(),
|
||||||
|
),
|
||||||
AttributeLoc::Param(0),
|
AttributeLoc::Param(0),
|
||||||
)];
|
)];
|
||||||
attributes.append(&mut vmctx_attributes(1));
|
attributes.append(&mut vmctx_attributes(1));
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use crate::address_map::get_function_address_map;
|
use crate::address_map::get_function_address_map;
|
||||||
use crate::{common_decl::*, config::Singlepass, emitter_x64::*, machine::Machine, x64_decl::*};
|
use crate::{common_decl::*, config::Singlepass, emitter_x64::*, machine::Machine, x64_decl::*};
|
||||||
use dynasmrt::{x64::Assembler, DynamicLabel};
|
use dynasmrt::{x64::X64Relocation, DynamicLabel, VecAssembler};
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
@@ -22,6 +22,8 @@ use wasmer_types::{
|
|||||||
};
|
};
|
||||||
use wasmer_vm::{MemoryStyle, TableStyle, TrapCode, VMBuiltinFunctionIndex, VMOffsets};
|
use wasmer_vm::{MemoryStyle, TableStyle, TrapCode, VMBuiltinFunctionIndex, VMOffsets};
|
||||||
|
|
||||||
|
type Assembler = VecAssembler<X64Relocation>;
|
||||||
|
|
||||||
/// The singlepass per-function code generator.
|
/// The singlepass per-function code generator.
|
||||||
pub struct FuncGen<'a> {
|
pub struct FuncGen<'a> {
|
||||||
// Immutable properties assigned at creation time.
|
// Immutable properties assigned at creation time.
|
||||||
@@ -89,6 +91,9 @@ pub struct FuncGen<'a> {
|
|||||||
///
|
///
|
||||||
// Ordered by increasing InstructionAddressMap::srcloc.
|
// Ordered by increasing InstructionAddressMap::srcloc.
|
||||||
instructions_address_map: Vec<InstructionAddressMap>,
|
instructions_address_map: Vec<InstructionAddressMap>,
|
||||||
|
|
||||||
|
/// Calling convention to use.
|
||||||
|
calling_convention: CallingConvention,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SpecialLabelSet {
|
struct SpecialLabelSet {
|
||||||
@@ -1010,7 +1015,7 @@ impl<'a> FuncGen<'a> {
|
|||||||
self.machine.state.stack_values.push(content);
|
self.machine.state.stack_values.push(content);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let calling_convention = self.config.calling_convention;
|
let calling_convention = self.calling_convention;
|
||||||
|
|
||||||
let stack_padding: usize = match calling_convention {
|
let stack_padding: usize = match calling_convention {
|
||||||
CallingConvention::WindowsFastcall => 32,
|
CallingConvention::WindowsFastcall => 32,
|
||||||
@@ -1756,7 +1761,7 @@ impl<'a> FuncGen<'a> {
|
|||||||
&mut self.assembler,
|
&mut self.assembler,
|
||||||
self.local_types.len(),
|
self.local_types.len(),
|
||||||
self.signature.params().len(),
|
self.signature.params().len(),
|
||||||
self.config.calling_convention,
|
self.calling_convention,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Mark vmctx register. The actual loading of the vmctx value is handled by init_local.
|
// Mark vmctx register. The actual loading of the vmctx value is handled by init_local.
|
||||||
@@ -1823,6 +1828,7 @@ impl<'a> FuncGen<'a> {
|
|||||||
_table_styles: &'a PrimaryMap<TableIndex, TableStyle>,
|
_table_styles: &'a PrimaryMap<TableIndex, TableStyle>,
|
||||||
local_func_index: LocalFunctionIndex,
|
local_func_index: LocalFunctionIndex,
|
||||||
local_types_excluding_arguments: &[WpType],
|
local_types_excluding_arguments: &[WpType],
|
||||||
|
calling_convention: CallingConvention,
|
||||||
) -> Result<FuncGen<'a>, CodegenError> {
|
) -> Result<FuncGen<'a>, CodegenError> {
|
||||||
let func_index = module.func_index(local_func_index);
|
let func_index = module.func_index(local_func_index);
|
||||||
let sig_index = module.functions[func_index];
|
let sig_index = module.functions[func_index];
|
||||||
@@ -1844,7 +1850,7 @@ impl<'a> FuncGen<'a> {
|
|||||||
.collect(),
|
.collect(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut assembler = Assembler::new().unwrap();
|
let mut assembler = Assembler::new(0);
|
||||||
let special_labels = SpecialLabelSet {
|
let special_labels = SpecialLabelSet {
|
||||||
integer_division_by_zero: assembler.get_label(),
|
integer_division_by_zero: assembler.get_label(),
|
||||||
heap_access_oob: assembler.get_label(),
|
heap_access_oob: assembler.get_label(),
|
||||||
@@ -1874,6 +1880,7 @@ impl<'a> FuncGen<'a> {
|
|||||||
special_labels,
|
special_labels,
|
||||||
src_loc: 0,
|
src_loc: 0,
|
||||||
instructions_address_map: vec![],
|
instructions_address_map: vec![],
|
||||||
|
calling_convention,
|
||||||
};
|
};
|
||||||
fg.emit_head()?;
|
fg.emit_head()?;
|
||||||
Ok(fg)
|
Ok(fg)
|
||||||
@@ -5404,7 +5411,7 @@ impl<'a> FuncGen<'a> {
|
|||||||
self.vmoffsets.vmcaller_checked_anyfunc_func_ptr() as usize;
|
self.vmoffsets.vmcaller_checked_anyfunc_func_ptr() as usize;
|
||||||
let vmcaller_checked_anyfunc_vmctx =
|
let vmcaller_checked_anyfunc_vmctx =
|
||||||
self.vmoffsets.vmcaller_checked_anyfunc_vmctx() as usize;
|
self.vmoffsets.vmcaller_checked_anyfunc_vmctx() as usize;
|
||||||
let calling_convention = self.config.calling_convention;
|
let calling_convention = self.calling_convention;
|
||||||
|
|
||||||
self.emit_call_native(
|
self.emit_call_native(
|
||||||
|this| {
|
|this| {
|
||||||
@@ -6698,7 +6705,7 @@ impl<'a> FuncGen<'a> {
|
|||||||
self.machine.finalize_locals(
|
self.machine.finalize_locals(
|
||||||
&mut self.assembler,
|
&mut self.assembler,
|
||||||
&self.locals,
|
&self.locals,
|
||||||
self.config.calling_convention,
|
self.calling_convention,
|
||||||
);
|
);
|
||||||
self.assembler.emit_mov(
|
self.assembler.emit_mov(
|
||||||
Size::S64,
|
Size::S64,
|
||||||
@@ -8811,7 +8818,7 @@ pub fn gen_std_trampoline(
|
|||||||
sig: &FunctionType,
|
sig: &FunctionType,
|
||||||
calling_convention: CallingConvention,
|
calling_convention: CallingConvention,
|
||||||
) -> FunctionBody {
|
) -> FunctionBody {
|
||||||
let mut a = Assembler::new().unwrap();
|
let mut a = Assembler::new(0);
|
||||||
|
|
||||||
// Calculate stack offset.
|
// Calculate stack offset.
|
||||||
let mut stack_offset: u32 = 0;
|
let mut stack_offset: u32 = 0;
|
||||||
@@ -8921,7 +8928,7 @@ pub fn gen_std_dynamic_import_trampoline(
|
|||||||
sig: &FunctionType,
|
sig: &FunctionType,
|
||||||
calling_convention: CallingConvention,
|
calling_convention: CallingConvention,
|
||||||
) -> FunctionBody {
|
) -> FunctionBody {
|
||||||
let mut a = Assembler::new().unwrap();
|
let mut a = Assembler::new(0);
|
||||||
|
|
||||||
// Allocate argument array.
|
// Allocate argument array.
|
||||||
let stack_offset: usize = 16 * std::cmp::max(sig.params().len(), sig.results().len()) + 8; // 16 bytes each + 8 bytes sysv call padding
|
let stack_offset: usize = 16 * std::cmp::max(sig.params().len(), sig.results().len()) + 8; // 16 bytes each + 8 bytes sysv call padding
|
||||||
@@ -9043,7 +9050,7 @@ pub fn gen_import_call_trampoline(
|
|||||||
sig: &FunctionType,
|
sig: &FunctionType,
|
||||||
calling_convention: CallingConvention,
|
calling_convention: CallingConvention,
|
||||||
) -> CustomSection {
|
) -> CustomSection {
|
||||||
let mut a = Assembler::new().unwrap();
|
let mut a = Assembler::new(0);
|
||||||
|
|
||||||
// TODO: ARM entry trampoline is not emitted.
|
// TODO: ARM entry trampoline is not emitted.
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ use rayon::prelude::{IntoParallelIterator, ParallelIterator};
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use wasmer_compiler::{
|
use wasmer_compiler::{
|
||||||
Architecture, CallingConvention, Compilation, CompileError, CompileModuleInfo,
|
Architecture, CallingConvention, Compilation, CompileError, CompileModuleInfo,
|
||||||
CompiledFunction, Compiler, CompilerConfig, FunctionBinaryReader, FunctionBody,
|
CompiledFunction, Compiler, CompilerConfig, CpuFeature, FunctionBinaryReader, FunctionBody,
|
||||||
FunctionBodyData, MiddlewareBinaryReader, ModuleMiddleware, ModuleMiddlewareChain,
|
FunctionBodyData, MiddlewareBinaryReader, ModuleMiddleware, ModuleMiddlewareChain,
|
||||||
ModuleTranslationState, OperatingSystem, SectionIndex, Target, TrapInformation,
|
ModuleTranslationState, OperatingSystem, SectionIndex, Target, TrapInformation,
|
||||||
};
|
};
|
||||||
@@ -62,8 +62,15 @@ impl Compiler for SinglepassCompiler {
|
|||||||
OperatingSystem::Windows.to_string(),
|
OperatingSystem::Windows.to_string(),
|
||||||
));
|
));
|
||||||
}*/
|
}*/
|
||||||
if let Architecture::X86_32(arch) = target.triple().architecture {
|
if target.triple().architecture != Architecture::X86_64 {
|
||||||
return Err(CompileError::UnsupportedTarget(arch.to_string()));
|
return Err(CompileError::UnsupportedTarget(
|
||||||
|
target.triple().architecture.to_string(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
if !target.cpu_features().contains(CpuFeature::AVX) {
|
||||||
|
return Err(CompileError::UnsupportedTarget(
|
||||||
|
"x86_64 without AVX".to_string(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
if compile_info.features.multi_value {
|
if compile_info.features.multi_value {
|
||||||
return Err(CompileError::UnsupportedFeature("multivalue".to_string()));
|
return Err(CompileError::UnsupportedFeature("multivalue".to_string()));
|
||||||
@@ -125,6 +132,7 @@ impl Compiler for SinglepassCompiler {
|
|||||||
&table_styles,
|
&table_styles,
|
||||||
i,
|
i,
|
||||||
&locals,
|
&locals,
|
||||||
|
calling_convention,
|
||||||
)
|
)
|
||||||
.map_err(to_compile_error)?;
|
.map_err(to_compile_error)?;
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,7 @@
|
|||||||
use crate::compiler::SinglepassCompiler;
|
use crate::compiler::SinglepassCompiler;
|
||||||
use loupe::MemoryUsage;
|
use loupe::MemoryUsage;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use wasmer_compiler::{
|
use wasmer_compiler::{Compiler, CompilerConfig, CpuFeature, ModuleMiddleware, Target};
|
||||||
CallingConvention, Compiler, CompilerConfig, CpuFeature, ModuleMiddleware, Target,
|
|
||||||
};
|
|
||||||
use wasmer_types::Features;
|
use wasmer_types::Features;
|
||||||
|
|
||||||
#[derive(Debug, Clone, MemoryUsage)]
|
#[derive(Debug, Clone, MemoryUsage)]
|
||||||
@@ -15,8 +13,6 @@ pub struct Singlepass {
|
|||||||
pub(crate) enable_stack_check: bool,
|
pub(crate) enable_stack_check: bool,
|
||||||
/// The middleware chain.
|
/// The middleware chain.
|
||||||
pub(crate) middlewares: Vec<Arc<dyn ModuleMiddleware>>,
|
pub(crate) middlewares: Vec<Arc<dyn ModuleMiddleware>>,
|
||||||
#[loupe(skip)]
|
|
||||||
pub(crate) calling_convention: CallingConvention,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Singlepass {
|
impl Singlepass {
|
||||||
@@ -27,12 +23,6 @@ impl Singlepass {
|
|||||||
enable_nan_canonicalization: true,
|
enable_nan_canonicalization: true,
|
||||||
enable_stack_check: false,
|
enable_stack_check: false,
|
||||||
middlewares: vec![],
|
middlewares: vec![],
|
||||||
calling_convention: match Target::default().triple().default_calling_convention() {
|
|
||||||
Ok(CallingConvention::WindowsFastcall) => CallingConvention::WindowsFastcall,
|
|
||||||
Ok(CallingConvention::SystemV) => CallingConvention::SystemV,
|
|
||||||
//Ok(CallingConvention::AppleAarch64) => AppleAarch64,
|
|
||||||
_ => panic!("Unsupported Calling convention for Singlepass"),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
pub use crate::x64_decl::{GPR, XMM};
|
pub use crate::x64_decl::{GPR, XMM};
|
||||||
use dynasm::dynasm;
|
use dynasm::dynasm;
|
||||||
use dynasmrt::{x64::Assembler, AssemblyOffset, DynamicLabel, DynasmApi, DynasmLabelApi};
|
use dynasmrt::{
|
||||||
|
x64::X64Relocation, AssemblyOffset, DynamicLabel, DynasmApi, DynasmLabelApi, VecAssembler,
|
||||||
|
};
|
||||||
|
|
||||||
|
type Assembler = VecAssembler<X64Relocation>;
|
||||||
|
|
||||||
/// Force `dynasm!` to use the correct arch (x64) when cross-compiling.
|
/// Force `dynasm!` to use the correct arch (x64) when cross-compiling.
|
||||||
/// `dynasm!` proc-macro tries to auto-detect it by default by looking at the
|
/// `dynasm!` proc-macro tries to auto-detect it by default by looking at the
|
||||||
@@ -479,7 +483,7 @@ macro_rules! binop_shift {
|
|||||||
|
|
||||||
macro_rules! jmp_op {
|
macro_rules! jmp_op {
|
||||||
($ins:ident, $assembler:tt, $label:ident) => {
|
($ins:ident, $assembler:tt, $label:ident) => {
|
||||||
dynasm!($assembler ; $ins =>$label);
|
dynasm!($assembler ; $ins =>$label)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -586,12 +586,14 @@ impl Machine {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use dynasmrt::x64::Assembler;
|
use dynasmrt::x64::X64Relocation;
|
||||||
|
use dynasmrt::VecAssembler;
|
||||||
|
type Assembler = VecAssembler<X64Relocation>;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_release_locations_keep_state_nopanic() {
|
fn test_release_locations_keep_state_nopanic() {
|
||||||
let mut machine = Machine::new();
|
let mut machine = Machine::new();
|
||||||
let mut assembler = Assembler::new().unwrap();
|
let mut assembler = Assembler::new(0);
|
||||||
let locs = machine.acquire_locations(
|
let locs = machine.acquire_locations(
|
||||||
&mut assembler,
|
&mut assembler,
|
||||||
&(0..10)
|
&(0..10)
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ serde = { version = "1.0", features = ["derive"], optional = true }
|
|||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
serde_bytes = { version = "0.11", optional = true }
|
serde_bytes = { version = "0.11", optional = true }
|
||||||
smallvec = "1.6"
|
smallvec = "1.6"
|
||||||
rkyv = { version = "0.6.1", optional = true }
|
rkyv = { version = "0.7.20", optional = true }
|
||||||
loupe = "0.1"
|
loupe = "0.1"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ use wasmer_types::entity::entity_impl;
|
|||||||
)]
|
)]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "enable-rkyv",
|
feature = "enable-rkyv",
|
||||||
archive(derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug))
|
archive_attr(derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug))
|
||||||
)]
|
)]
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, MemoryUsage)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, MemoryUsage)]
|
||||||
pub struct SectionIndex(u32);
|
pub struct SectionIndex(u32);
|
||||||
|
|||||||
@@ -23,8 +23,9 @@ leb128 = "0.2"
|
|||||||
libloading = "0.7"
|
libloading = "0.7"
|
||||||
tempfile = "3.1"
|
tempfile = "3.1"
|
||||||
which = "4.0"
|
which = "4.0"
|
||||||
rkyv = "0.6.1"
|
rkyv = "0.7.20"
|
||||||
loupe = "0.1"
|
loupe = "0.1"
|
||||||
|
enumset = "1.0"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
# Enable the `compiler` feature if you want the engine to compile
|
# Enable the `compiler` feature if you want the engine to compile
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
use crate::engine::{DylibEngine, DylibEngineInner};
|
use crate::engine::{DylibEngine, DylibEngineInner};
|
||||||
use crate::serialize::{ArchivedModuleMetadata, ModuleMetadata};
|
use crate::serialize::{ArchivedModuleMetadata, ModuleMetadata};
|
||||||
|
use enumset::EnumSet;
|
||||||
use libloading::{Library, Symbol as LibrarySymbol};
|
use libloading::{Library, Symbol as LibrarySymbol};
|
||||||
use loupe::MemoryUsage;
|
use loupe::MemoryUsage;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
@@ -17,8 +18,8 @@ use tracing::log::error;
|
|||||||
#[cfg(feature = "compiler")]
|
#[cfg(feature = "compiler")]
|
||||||
use tracing::trace;
|
use tracing::trace;
|
||||||
use wasmer_compiler::{
|
use wasmer_compiler::{
|
||||||
Architecture, CompileError, CompiledFunctionFrameInfo, Features, FunctionAddressMap,
|
Architecture, CompileError, CompiledFunctionFrameInfo, CpuFeature, Features,
|
||||||
OperatingSystem, Symbol, SymbolRegistry, Triple,
|
FunctionAddressMap, OperatingSystem, Symbol, SymbolRegistry, Triple,
|
||||||
};
|
};
|
||||||
#[cfg(feature = "compiler")]
|
#[cfg(feature = "compiler")]
|
||||||
use wasmer_compiler::{
|
use wasmer_compiler::{
|
||||||
@@ -211,6 +212,7 @@ impl DylibArtifact {
|
|||||||
prefix: engine_inner.get_prefix(&data),
|
prefix: engine_inner.get_prefix(&data),
|
||||||
data_initializers,
|
data_initializers,
|
||||||
function_body_lengths,
|
function_body_lengths,
|
||||||
|
cpu_features: target.cpu_features().as_u64(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let serialized_data = metadata.serialize()?;
|
let serialized_data = metadata.serialize()?;
|
||||||
@@ -800,6 +802,10 @@ impl Artifact for DylibArtifact {
|
|||||||
&self.metadata.compile_info.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] {
|
fn data_initializers(&self) -> &[OwnedDataInitializer] {
|
||||||
&*self.metadata.data_initializers
|
&*self.metadata.data_initializers
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
use loupe::MemoryUsage;
|
use loupe::MemoryUsage;
|
||||||
use rkyv::{
|
use rkyv::{
|
||||||
archived_value,
|
archived_value, de::deserializers::SharedDeserializeMap, ser::serializers::AllocSerializer,
|
||||||
de::{adapters::SharedDeserializerAdapter, deserializers::AllocDeserializer},
|
ser::Serializer as RkyvSerializer, Archive, Deserialize as RkyvDeserialize,
|
||||||
ser::adapters::SharedSerializerAdapter,
|
Serialize as RkyvSerialize,
|
||||||
ser::{serializers::WriteSerializer, Serializer as RkyvSerializer},
|
|
||||||
Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize,
|
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
@@ -35,6 +33,7 @@ pub struct ModuleMetadata {
|
|||||||
pub data_initializers: Box<[OwnedDataInitializer]>,
|
pub data_initializers: Box<[OwnedDataInitializer]>,
|
||||||
// The function body lengths (used to find function by address)
|
// The function body lengths (used to find function by address)
|
||||||
pub function_body_lengths: PrimaryMap<LocalFunctionIndex, u64>,
|
pub function_body_lengths: PrimaryMap<LocalFunctionIndex, u64>,
|
||||||
|
pub cpu_features: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ModuleMetadataSymbolRegistry<'a> {
|
pub struct ModuleMetadataSymbolRegistry<'a> {
|
||||||
@@ -59,11 +58,11 @@ impl ModuleMetadata {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn serialize(&mut self) -> Result<Vec<u8>, CompileError> {
|
pub fn serialize(&mut self) -> Result<Vec<u8>, CompileError> {
|
||||||
let mut serializer = SharedSerializerAdapter::new(WriteSerializer::new(vec![]));
|
let mut serializer = AllocSerializer::<4096>::default();
|
||||||
let pos = serializer.serialize_value(self).map_err(to_compile_error)? as u64;
|
let pos = serializer.serialize_value(self).map_err(to_compile_error)? as u64;
|
||||||
let mut serialized_data = serializer.into_inner().into_inner();
|
let mut serialized_data = serializer.into_serializer().into_inner();
|
||||||
serialized_data.extend_from_slice(&pos.to_le_bytes());
|
serialized_data.extend_from_slice(&pos.to_le_bytes());
|
||||||
Ok(serialized_data)
|
Ok(serialized_data.to_vec())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn deserialize(metadata_slice: &[u8]) -> Result<Self, DeserializeError> {
|
pub unsafe fn deserialize(metadata_slice: &[u8]) -> Result<Self, DeserializeError> {
|
||||||
@@ -86,7 +85,7 @@ impl ModuleMetadata {
|
|||||||
pub fn deserialize_from_archive(
|
pub fn deserialize_from_archive(
|
||||||
archived: &ArchivedModuleMetadata,
|
archived: &ArchivedModuleMetadata,
|
||||||
) -> Result<Self, DeserializeError> {
|
) -> Result<Self, DeserializeError> {
|
||||||
let mut deserializer = SharedDeserializerAdapter::new(AllocDeserializer);
|
let mut deserializer = SharedDeserializeMap::new();
|
||||||
RkyvDeserialize::deserialize(archived, &mut deserializer)
|
RkyvDeserialize::deserialize(archived, &mut deserializer)
|
||||||
.map_err(|e| DeserializeError::CorruptedBinary(format!("{:?}", e)))
|
.map_err(|e| DeserializeError::CorruptedBinary(format!("{:?}", e)))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ leb128 = "0.2"
|
|||||||
libloading = "0.7"
|
libloading = "0.7"
|
||||||
tempfile = "3.1"
|
tempfile = "3.1"
|
||||||
loupe = "0.1"
|
loupe = "0.1"
|
||||||
|
enumset = "1.0"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
# Enable the `compiler` feature if you want the engine to compile
|
# Enable the `compiler` feature if you want the engine to compile
|
||||||
|
|||||||
@@ -3,12 +3,15 @@
|
|||||||
|
|
||||||
use crate::engine::{StaticlibEngine, StaticlibEngineInner};
|
use crate::engine::{StaticlibEngine, StaticlibEngineInner};
|
||||||
use crate::serialize::{ModuleMetadata, ModuleMetadataSymbolRegistry};
|
use crate::serialize::{ModuleMetadata, ModuleMetadataSymbolRegistry};
|
||||||
|
use enumset::EnumSet;
|
||||||
use loupe::MemoryUsage;
|
use loupe::MemoryUsage;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use wasmer_compiler::{CompileError, Features, OperatingSystem, SymbolRegistry, Triple};
|
use wasmer_compiler::{
|
||||||
|
CompileError, CpuFeature, Features, OperatingSystem, SymbolRegistry, Triple,
|
||||||
|
};
|
||||||
#[cfg(feature = "compiler")]
|
#[cfg(feature = "compiler")]
|
||||||
use wasmer_compiler::{
|
use wasmer_compiler::{
|
||||||
CompileModuleInfo, Compiler, FunctionBodyData, ModuleEnvironment, ModuleMiddlewareChain,
|
CompileModuleInfo, Compiler, FunctionBodyData, ModuleEnvironment, ModuleMiddlewareChain,
|
||||||
@@ -46,6 +49,7 @@ pub struct StaticlibArtifact {
|
|||||||
/// Length of the serialized metadata
|
/// Length of the serialized metadata
|
||||||
metadata_length: usize,
|
metadata_length: usize,
|
||||||
symbol_registry: ModuleMetadataSymbolRegistry,
|
symbol_registry: ModuleMetadataSymbolRegistry,
|
||||||
|
is_compiled: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@@ -181,6 +185,7 @@ impl StaticlibArtifact {
|
|||||||
prefix: engine_inner.get_prefix(&data),
|
prefix: engine_inner.get_prefix(&data),
|
||||||
data_initializers,
|
data_initializers,
|
||||||
function_body_lengths,
|
function_body_lengths,
|
||||||
|
cpu_features: target.cpu_features().as_u64(),
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -295,6 +300,7 @@ impl StaticlibArtifact {
|
|||||||
func_data_registry: engine_inner.func_data().clone(),
|
func_data_registry: engine_inner.func_data().clone(),
|
||||||
metadata_length,
|
metadata_length,
|
||||||
symbol_registry,
|
symbol_registry,
|
||||||
|
is_compiled: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -415,6 +421,7 @@ impl StaticlibArtifact {
|
|||||||
func_data_registry,
|
func_data_registry,
|
||||||
metadata_length: 0,
|
metadata_length: 0,
|
||||||
symbol_registry,
|
symbol_registry,
|
||||||
|
is_compiled: false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -450,6 +457,10 @@ impl Artifact for StaticlibArtifact {
|
|||||||
&self.metadata.compile_info.features
|
&self.metadata.compile_info.features
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn cpu_features(&self) -> EnumSet<CpuFeature> {
|
||||||
|
EnumSet::from_u64(self.metadata.cpu_features)
|
||||||
|
}
|
||||||
|
|
||||||
fn data_initializers(&self) -> &[OwnedDataInitializer] {
|
fn data_initializers(&self) -> &[OwnedDataInitializer] {
|
||||||
&*self.metadata.data_initializers
|
&*self.metadata.data_initializers
|
||||||
}
|
}
|
||||||
@@ -483,6 +494,12 @@ impl Artifact for StaticlibArtifact {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn preinstantiate(&self) -> Result<(), InstantiationError> {
|
fn preinstantiate(&self) -> Result<(), InstantiationError> {
|
||||||
|
if self.is_compiled {
|
||||||
|
panic!(
|
||||||
|
"a module built with the staticlib engine must be linked \
|
||||||
|
into the current executable"
|
||||||
|
);
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ pub struct ModuleMetadata {
|
|||||||
pub data_initializers: Box<[OwnedDataInitializer]>,
|
pub data_initializers: Box<[OwnedDataInitializer]>,
|
||||||
// The function body lengths (used to find function by address)
|
// The function body lengths (used to find function by address)
|
||||||
pub function_body_lengths: PrimaryMap<LocalFunctionIndex, u64>,
|
pub function_body_lengths: PrimaryMap<LocalFunctionIndex, u64>,
|
||||||
|
pub cpu_features: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(MemoryUsage)]
|
#[derive(MemoryUsage)]
|
||||||
|
|||||||
@@ -11,16 +11,22 @@ readme = "README.md"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wasmer-types = { path = "../types", version = "2.0.0", features = ["enable-rkyv"] }
|
wasmer-types = { path = "../types", version = "2.0.0", features = [
|
||||||
wasmer-compiler = { path = "../compiler", version = "2.0.0", features = ["translator", "enable-rkyv"] }
|
"enable-rkyv",
|
||||||
|
] }
|
||||||
|
wasmer-compiler = { path = "../compiler", version = "2.0.0", features = [
|
||||||
|
"translator",
|
||||||
|
"enable-rkyv",
|
||||||
|
] }
|
||||||
wasmer-vm = { path = "../vm", version = "2.0.0", features = ["enable-rkyv"] }
|
wasmer-vm = { path = "../vm", version = "2.0.0", features = ["enable-rkyv"] }
|
||||||
wasmer-engine = { path = "../engine", version = "2.0.0" }
|
wasmer-engine = { path = "../engine", version = "2.0.0" }
|
||||||
# flexbuffers = { path = "../../../flatbuffers/rust/flexbuffers", version = "0.1.0" }
|
# flexbuffers = { path = "../../../flatbuffers/rust/flexbuffers", version = "0.1.0" }
|
||||||
region = "3.0"
|
region = "3.0"
|
||||||
cfg-if = "1.0"
|
cfg-if = "1.0"
|
||||||
leb128 = "0.2"
|
leb128 = "0.2"
|
||||||
rkyv = "0.6.1"
|
rkyv = "0.7.20"
|
||||||
loupe = "0.1"
|
loupe = "0.1"
|
||||||
|
enumset = "1.0"
|
||||||
|
|
||||||
[target.'cfg(target_os = "windows")'.dependencies]
|
[target.'cfg(target_os = "windows")'.dependencies]
|
||||||
winapi = { version = "0.3", features = ["winnt", "impl-default"] }
|
winapi = { version = "0.3", features = ["winnt", "impl-default"] }
|
||||||
|
|||||||
@@ -6,9 +6,10 @@ use crate::link::link_module;
|
|||||||
#[cfg(feature = "compiler")]
|
#[cfg(feature = "compiler")]
|
||||||
use crate::serialize::SerializableCompilation;
|
use crate::serialize::SerializableCompilation;
|
||||||
use crate::serialize::SerializableModule;
|
use crate::serialize::SerializableModule;
|
||||||
|
use enumset::EnumSet;
|
||||||
use loupe::MemoryUsage;
|
use loupe::MemoryUsage;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use wasmer_compiler::{CompileError, Features, Triple};
|
use wasmer_compiler::{CompileError, CpuFeature, Features, Triple};
|
||||||
#[cfg(feature = "compiler")]
|
#[cfg(feature = "compiler")]
|
||||||
use wasmer_compiler::{CompileModuleInfo, ModuleEnvironment, ModuleMiddlewareChain};
|
use wasmer_compiler::{CompileModuleInfo, ModuleEnvironment, ModuleMiddlewareChain};
|
||||||
use wasmer_engine::{
|
use wasmer_engine::{
|
||||||
@@ -128,6 +129,7 @@ impl UniversalArtifact {
|
|||||||
compilation: serializable_compilation,
|
compilation: serializable_compilation,
|
||||||
compile_info,
|
compile_info,
|
||||||
data_initializers,
|
data_initializers,
|
||||||
|
cpu_features: engine.target().cpu_features().as_u64(),
|
||||||
};
|
};
|
||||||
Self::from_parts(&mut inner_engine, serializable)
|
Self::from_parts(&mut inner_engine, serializable)
|
||||||
}
|
}
|
||||||
@@ -307,6 +309,10 @@ impl Artifact for UniversalArtifact {
|
|||||||
&self.serializable.compile_info.features
|
&self.serializable.compile_info.features
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn cpu_features(&self) -> EnumSet<CpuFeature> {
|
||||||
|
EnumSet::from_u64(self.serializable.cpu_features)
|
||||||
|
}
|
||||||
|
|
||||||
fn data_initializers(&self) -> &[OwnedDataInitializer] {
|
fn data_initializers(&self) -> &[OwnedDataInitializer] {
|
||||||
&*self.serializable.data_initializers
|
&*self.serializable.data_initializers
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
use loupe::MemoryUsage;
|
use loupe::MemoryUsage;
|
||||||
use rkyv::{
|
use rkyv::{
|
||||||
archived_value,
|
archived_value, de::deserializers::SharedDeserializeMap, ser::serializers::AllocSerializer,
|
||||||
de::{adapters::SharedDeserializerAdapter, deserializers::AllocDeserializer},
|
ser::Serializer as RkyvSerializer, Archive, Deserialize as RkyvDeserialize,
|
||||||
ser::adapters::SharedSerializerAdapter,
|
Serialize as RkyvSerialize,
|
||||||
ser::{serializers::WriteSerializer, Serializer as RkyvSerializer},
|
|
||||||
Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize,
|
|
||||||
};
|
};
|
||||||
use wasmer_compiler::{
|
use wasmer_compiler::{
|
||||||
CompileModuleInfo, CompiledFunctionFrameInfo, CustomSection, Dwarf, FunctionBody,
|
CompileModuleInfo, CompiledFunctionFrameInfo, CustomSection, Dwarf, FunctionBody,
|
||||||
@@ -38,6 +36,7 @@ pub struct SerializableModule {
|
|||||||
pub compilation: SerializableCompilation,
|
pub compilation: SerializableCompilation,
|
||||||
pub compile_info: CompileModuleInfo,
|
pub compile_info: CompileModuleInfo,
|
||||||
pub data_initializers: Box<[OwnedDataInitializer]>,
|
pub data_initializers: Box<[OwnedDataInitializer]>,
|
||||||
|
pub cpu_features: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_serialize_error(err: impl std::error::Error) -> SerializeError {
|
fn to_serialize_error(err: impl std::error::Error) -> SerializeError {
|
||||||
@@ -49,13 +48,13 @@ impl SerializableModule {
|
|||||||
/// The bytes will have the following format:
|
/// The bytes will have the following format:
|
||||||
/// RKYV serialization (any length) + POS (8 bytes)
|
/// RKYV serialization (any length) + POS (8 bytes)
|
||||||
pub fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
|
pub fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
|
||||||
let mut serializer = SharedSerializerAdapter::new(WriteSerializer::new(vec![]));
|
let mut serializer = AllocSerializer::<4096>::default();
|
||||||
let pos = serializer
|
let pos = serializer
|
||||||
.serialize_value(self)
|
.serialize_value(self)
|
||||||
.map_err(to_serialize_error)? as u64;
|
.map_err(to_serialize_error)? as u64;
|
||||||
let mut serialized_data = serializer.into_inner().into_inner();
|
let mut serialized_data = serializer.into_serializer().into_inner();
|
||||||
serialized_data.extend_from_slice(&pos.to_le_bytes());
|
serialized_data.extend_from_slice(&pos.to_le_bytes());
|
||||||
Ok(serialized_data)
|
Ok(serialized_data.to_vec())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deserialize a Module from a slice.
|
/// Deserialize a Module from a slice.
|
||||||
@@ -98,7 +97,7 @@ impl SerializableModule {
|
|||||||
pub fn deserialize_from_archive(
|
pub fn deserialize_from_archive(
|
||||||
archived: &ArchivedSerializableModule,
|
archived: &ArchivedSerializableModule,
|
||||||
) -> Result<Self, DeserializeError> {
|
) -> Result<Self, DeserializeError> {
|
||||||
let mut deserializer = SharedDeserializerAdapter::new(AllocDeserializer);
|
let mut deserializer = SharedDeserializeMap::new();
|
||||||
RkyvDeserialize::deserialize(archived, &mut deserializer)
|
RkyvDeserialize::deserialize(archived, &mut deserializer)
|
||||||
.map_err(|e| DeserializeError::CorruptedBinary(format!("{:?}", e)))
|
.map_err(|e| DeserializeError::CorruptedBinary(format!("{:?}", e)))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ serde = { version = "1.0", features = ["derive", "rc"] }
|
|||||||
serde_bytes = { version = "0.11" }
|
serde_bytes = { version = "0.11" }
|
||||||
lazy_static = "1.4"
|
lazy_static = "1.4"
|
||||||
loupe = "0.1"
|
loupe = "0.1"
|
||||||
|
enumset = "1.0"
|
||||||
|
|
||||||
[badges]
|
[badges]
|
||||||
maintenance = { status = "actively-developed" }
|
maintenance = { status = "actively-developed" }
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
resolve_imports, InstantiationError, Resolver, RuntimeError, SerializeError, Tunables,
|
resolve_imports, InstantiationError, Resolver, RuntimeError, SerializeError, Tunables,
|
||||||
};
|
};
|
||||||
|
use enumset::EnumSet;
|
||||||
use loupe::MemoryUsage;
|
use loupe::MemoryUsage;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use wasmer_compiler::Features;
|
use wasmer_compiler::{CpuFeature, Features};
|
||||||
use wasmer_types::entity::{BoxedSlice, PrimaryMap};
|
use wasmer_types::entity::{BoxedSlice, PrimaryMap};
|
||||||
use wasmer_types::{
|
use wasmer_types::{
|
||||||
DataInitializer, FunctionIndex, LocalFunctionIndex, MemoryIndex, ModuleInfo,
|
DataInitializer, FunctionIndex, LocalFunctionIndex, MemoryIndex, ModuleInfo,
|
||||||
@@ -43,6 +44,9 @@ pub trait Artifact: Send + Sync + Upcastable + MemoryUsage {
|
|||||||
/// Returns the features for this Artifact
|
/// Returns the features for this Artifact
|
||||||
fn features(&self) -> &Features;
|
fn features(&self) -> &Features;
|
||||||
|
|
||||||
|
/// Returns the CPU features for this Artifact
|
||||||
|
fn cpu_features(&self) -> EnumSet<CpuFeature>;
|
||||||
|
|
||||||
/// Returns the memory styles associated with this `Artifact`.
|
/// Returns the memory styles associated with this `Artifact`.
|
||||||
fn memory_styles(&self) -> &PrimaryMap<MemoryIndex, MemoryStyle>;
|
fn memory_styles(&self) -> &PrimaryMap<MemoryIndex, MemoryStyle>;
|
||||||
|
|
||||||
@@ -96,6 +100,16 @@ pub trait Artifact: Send + Sync + Upcastable + MemoryUsage {
|
|||||||
resolver: &dyn Resolver,
|
resolver: &dyn Resolver,
|
||||||
host_state: Box<dyn Any>,
|
host_state: Box<dyn Any>,
|
||||||
) -> Result<InstanceHandle, InstantiationError> {
|
) -> Result<InstanceHandle, InstantiationError> {
|
||||||
|
// Validate the CPU features this module was compiled with against the
|
||||||
|
// host CPU features.
|
||||||
|
let host_cpu_features = CpuFeature::for_host();
|
||||||
|
if !host_cpu_features.is_superset(self.cpu_features()) {
|
||||||
|
Err(InstantiationError::CpuFeature(format!(
|
||||||
|
"{:?}",
|
||||||
|
self.cpu_features().difference(host_cpu_features)
|
||||||
|
)))?;
|
||||||
|
}
|
||||||
|
|
||||||
self.preinstantiate()?;
|
self.preinstantiate()?;
|
||||||
|
|
||||||
let module = self.module();
|
let module = self.module();
|
||||||
|
|||||||
@@ -91,6 +91,11 @@ pub enum InstantiationError {
|
|||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Link(LinkError),
|
Link(LinkError),
|
||||||
|
|
||||||
|
/// The module was compiled with a CPU feature that is not available on
|
||||||
|
/// the current host.
|
||||||
|
#[error("module compiled with CPU feature that is missing from host")]
|
||||||
|
CpuFeature(String),
|
||||||
|
|
||||||
/// A runtime error occured while invoking the start function
|
/// A runtime error occured while invoking the start function
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Start(RuntimeError),
|
Start(RuntimeError),
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ edition = "2018"
|
|||||||
serde = { version = "1.0", features = ["derive", "rc"], optional = true, default-features = false }
|
serde = { version = "1.0", features = ["derive", "rc"], optional = true, default-features = false }
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
indexmap = { version = "1.6", features = ["serde-1"] }
|
indexmap = { version = "1.6", features = ["serde-1"] }
|
||||||
rkyv = { version = "0.6.1", optional = true }
|
rkyv = { version = "0.7.20", optional = true }
|
||||||
loupe = { version = "0.1", features = ["enable-indexmap"] }
|
loupe = { version = "0.1", features = ["enable-indexmap"] }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
|||||||
@@ -3,32 +3,31 @@ use core::hash::Hash;
|
|||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use rkyv::{Archive, Deserialize, Serialize};
|
use rkyv::{Archive, Deserialize, Serialize};
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use std::{collections::HashMap, hash::Hash};
|
use std::hash::Hash;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Archive)]
|
#[derive(Serialize, Deserialize, Archive)]
|
||||||
/// Rkyv Archivable IndexMap
|
/// Rkyv Archivable IndexMap
|
||||||
pub struct ArchivableIndexMap<K: Hash + Eq + Archive, V: Archive> {
|
pub struct ArchivableIndexMap<K: Hash + Ord + Archive, V: Archive> {
|
||||||
indices: HashMap<K, u64>,
|
|
||||||
entries: Vec<(K, V)>,
|
entries: Vec<(K, V)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<K: Hash + Eq + Archive + Clone, V: Archive> From<IndexMap<K, V>> for ArchivableIndexMap<K, V> {
|
impl<K: Hash + Ord + Archive + Clone, V: Archive> From<IndexMap<K, V>>
|
||||||
|
for ArchivableIndexMap<K, V>
|
||||||
|
{
|
||||||
fn from(it: IndexMap<K, V>) -> ArchivableIndexMap<K, V> {
|
fn from(it: IndexMap<K, V>) -> ArchivableIndexMap<K, V> {
|
||||||
let mut r = ArchivableIndexMap {
|
let mut r = ArchivableIndexMap {
|
||||||
indices: HashMap::new(),
|
|
||||||
entries: Vec::new(),
|
entries: Vec::new(),
|
||||||
};
|
};
|
||||||
let mut i: u64 = 0;
|
|
||||||
for (k, v) in it.into_iter() {
|
for (k, v) in it.into_iter() {
|
||||||
r.indices.insert(k.clone(), i);
|
|
||||||
r.entries.push((k, v));
|
r.entries.push((k, v));
|
||||||
i += 1;
|
|
||||||
}
|
}
|
||||||
r
|
r
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<K: Hash + Eq + Archive + Clone, V: Archive> Into<IndexMap<K, V>> for ArchivableIndexMap<K, V> {
|
impl<K: Hash + Ord + Archive + Clone, V: Archive> Into<IndexMap<K, V>>
|
||||||
|
for ArchivableIndexMap<K, V>
|
||||||
|
{
|
||||||
fn into(self) -> IndexMap<K, V> {
|
fn into(self) -> IndexMap<K, V> {
|
||||||
let mut r = IndexMap::new();
|
let mut r = IndexMap::new();
|
||||||
for (k, v) in self.entries.into_iter() {
|
for (k, v) in self.entries.into_iter() {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
)]
|
)]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "enable-rkyv",
|
feature = "enable-rkyv",
|
||||||
archive(derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug))
|
archive_attr(derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug))
|
||||||
)]
|
)]
|
||||||
pub struct LocalFunctionIndex(u32);
|
pub struct LocalFunctionIndex(u32);
|
||||||
entity_impl!(LocalFunctionIndex);
|
entity_impl!(LocalFunctionIndex);
|
||||||
@@ -44,7 +44,7 @@ entity_impl!(LocalMemoryIndex);
|
|||||||
)]
|
)]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "enable-rkyv",
|
feature = "enable-rkyv",
|
||||||
archive(derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug))
|
archive_attr(derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug))
|
||||||
)]
|
)]
|
||||||
pub struct LocalGlobalIndex(u32);
|
pub struct LocalGlobalIndex(u32);
|
||||||
entity_impl!(LocalGlobalIndex);
|
entity_impl!(LocalGlobalIndex);
|
||||||
@@ -60,7 +60,7 @@ entity_impl!(ArchivedLocalGlobalIndex);
|
|||||||
)]
|
)]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "enable-rkyv",
|
feature = "enable-rkyv",
|
||||||
archive(derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug))
|
archive_attr(derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug))
|
||||||
)]
|
)]
|
||||||
pub struct FunctionIndex(u32);
|
pub struct FunctionIndex(u32);
|
||||||
entity_impl!(FunctionIndex);
|
entity_impl!(FunctionIndex);
|
||||||
@@ -76,7 +76,7 @@ entity_impl!(ArchivedFunctionIndex);
|
|||||||
)]
|
)]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "enable-rkyv",
|
feature = "enable-rkyv",
|
||||||
archive(derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug))
|
archive_attr(derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug))
|
||||||
)]
|
)]
|
||||||
pub struct TableIndex(u32);
|
pub struct TableIndex(u32);
|
||||||
entity_impl!(TableIndex);
|
entity_impl!(TableIndex);
|
||||||
@@ -92,7 +92,7 @@ entity_impl!(ArchivedTableIndex);
|
|||||||
)]
|
)]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "enable-rkyv",
|
feature = "enable-rkyv",
|
||||||
archive(derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug))
|
archive_attr(derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug))
|
||||||
)]
|
)]
|
||||||
pub struct GlobalIndex(u32);
|
pub struct GlobalIndex(u32);
|
||||||
entity_impl!(GlobalIndex);
|
entity_impl!(GlobalIndex);
|
||||||
@@ -108,7 +108,7 @@ entity_impl!(ArchivedGlobalIndex);
|
|||||||
)]
|
)]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "enable-rkyv",
|
feature = "enable-rkyv",
|
||||||
archive(derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug))
|
archive_attr(derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug))
|
||||||
)]
|
)]
|
||||||
pub struct MemoryIndex(u32);
|
pub struct MemoryIndex(u32);
|
||||||
entity_impl!(MemoryIndex);
|
entity_impl!(MemoryIndex);
|
||||||
@@ -124,7 +124,7 @@ entity_impl!(ArchivedMemoryIndex);
|
|||||||
)]
|
)]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "enable-rkyv",
|
feature = "enable-rkyv",
|
||||||
archive(derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug))
|
archive_attr(derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug))
|
||||||
)]
|
)]
|
||||||
pub struct SignatureIndex(u32);
|
pub struct SignatureIndex(u32);
|
||||||
entity_impl!(SignatureIndex);
|
entity_impl!(SignatureIndex);
|
||||||
@@ -140,7 +140,7 @@ entity_impl!(ArchivedSignatureIndex);
|
|||||||
)]
|
)]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "enable-rkyv",
|
feature = "enable-rkyv",
|
||||||
archive(derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug))
|
archive_attr(derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug))
|
||||||
)]
|
)]
|
||||||
pub struct DataIndex(u32);
|
pub struct DataIndex(u32);
|
||||||
entity_impl!(DataIndex);
|
entity_impl!(DataIndex);
|
||||||
@@ -156,7 +156,7 @@ entity_impl!(ArchivedDataIndex);
|
|||||||
)]
|
)]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "enable-rkyv",
|
feature = "enable-rkyv",
|
||||||
archive(derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug))
|
archive_attr(derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug))
|
||||||
)]
|
)]
|
||||||
pub struct ElemIndex(u32);
|
pub struct ElemIndex(u32);
|
||||||
entity_impl!(ElemIndex);
|
entity_impl!(ElemIndex);
|
||||||
@@ -172,7 +172,7 @@ entity_impl!(ArchivedElemIndex);
|
|||||||
)]
|
)]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "enable-rkyv",
|
feature = "enable-rkyv",
|
||||||
archive(derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug))
|
archive_attr(derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug))
|
||||||
)]
|
)]
|
||||||
pub struct CustomSectionIndex(u32);
|
pub struct CustomSectionIndex(u32);
|
||||||
entity_impl!(CustomSectionIndex);
|
entity_impl!(CustomSectionIndex);
|
||||||
@@ -188,7 +188,7 @@ entity_impl!(ArchivedCustomSectionIndex);
|
|||||||
)]
|
)]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "enable-rkyv",
|
feature = "enable-rkyv",
|
||||||
archive(derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug))
|
archive_attr(derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug))
|
||||||
)]
|
)]
|
||||||
pub enum ExportIndex {
|
pub enum ExportIndex {
|
||||||
/// Function export.
|
/// Function export.
|
||||||
@@ -210,7 +210,7 @@ pub enum ExportIndex {
|
|||||||
)]
|
)]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "enable-rkyv",
|
feature = "enable-rkyv",
|
||||||
archive(derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug))
|
archive_attr(derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug))
|
||||||
)]
|
)]
|
||||||
pub enum ImportIndex {
|
pub enum ImportIndex {
|
||||||
/// Function import.
|
/// Function import.
|
||||||
|
|||||||
@@ -17,16 +17,17 @@ use indexmap::IndexMap;
|
|||||||
use loupe::MemoryUsage;
|
use loupe::MemoryUsage;
|
||||||
#[cfg(feature = "enable-rkyv")]
|
#[cfg(feature = "enable-rkyv")]
|
||||||
use rkyv::{
|
use rkyv::{
|
||||||
de::SharedDeserializer, ser::Serializer, ser::SharedSerializer, Archive, Archived,
|
de::SharedDeserializeRegistry, ser::ScratchSpace, ser::Serializer,
|
||||||
Deserialize as RkyvDeserialize, Fallible, Serialize as RkyvSerialize,
|
ser::SharedSerializeRegistry, Archive, Archived, Deserialize as RkyvDeserialize, Fallible,
|
||||||
|
Serialize as RkyvSerialize,
|
||||||
};
|
};
|
||||||
#[cfg(feature = "enable-serde")]
|
#[cfg(feature = "enable-serde")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
#[cfg(feature = "enable-rkyv")]
|
||||||
|
use std::collections::BTreeMap;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::iter::ExactSizeIterator;
|
use std::iter::ExactSizeIterator;
|
||||||
#[cfg(feature = "enable-rkyv")]
|
|
||||||
use std::mem::MaybeUninit;
|
|
||||||
use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};
|
use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
@@ -142,10 +143,10 @@ pub struct ArchivableModuleInfo {
|
|||||||
exports: ArchivableIndexMap<String, ExportIndex>,
|
exports: ArchivableIndexMap<String, ExportIndex>,
|
||||||
start_function: Option<FunctionIndex>,
|
start_function: Option<FunctionIndex>,
|
||||||
table_initializers: Vec<TableInitializer>,
|
table_initializers: Vec<TableInitializer>,
|
||||||
passive_elements: HashMap<ElemIndex, Box<[FunctionIndex]>>,
|
passive_elements: BTreeMap<ElemIndex, Box<[FunctionIndex]>>,
|
||||||
passive_data: HashMap<DataIndex, Arc<[u8]>>,
|
passive_data: BTreeMap<DataIndex, Arc<[u8]>>,
|
||||||
global_initializers: PrimaryMap<LocalGlobalIndex, GlobalInit>,
|
global_initializers: PrimaryMap<LocalGlobalIndex, GlobalInit>,
|
||||||
function_names: HashMap<FunctionIndex, String>,
|
function_names: BTreeMap<FunctionIndex, String>,
|
||||||
signatures: PrimaryMap<SignatureIndex, FunctionType>,
|
signatures: PrimaryMap<SignatureIndex, FunctionType>,
|
||||||
functions: PrimaryMap<FunctionIndex, SignatureIndex>,
|
functions: PrimaryMap<FunctionIndex, SignatureIndex>,
|
||||||
tables: PrimaryMap<TableIndex, TableType>,
|
tables: PrimaryMap<TableIndex, TableType>,
|
||||||
@@ -168,10 +169,10 @@ impl From<ModuleInfo> for ArchivableModuleInfo {
|
|||||||
exports: ArchivableIndexMap::from(it.exports),
|
exports: ArchivableIndexMap::from(it.exports),
|
||||||
start_function: it.start_function,
|
start_function: it.start_function,
|
||||||
table_initializers: it.table_initializers,
|
table_initializers: it.table_initializers,
|
||||||
passive_elements: it.passive_elements,
|
passive_elements: it.passive_elements.into_iter().collect(),
|
||||||
passive_data: it.passive_data,
|
passive_data: it.passive_data.into_iter().collect(),
|
||||||
global_initializers: it.global_initializers,
|
global_initializers: it.global_initializers,
|
||||||
function_names: it.function_names,
|
function_names: it.function_names.into_iter().collect(),
|
||||||
signatures: it.signatures,
|
signatures: it.signatures,
|
||||||
functions: it.functions,
|
functions: it.functions,
|
||||||
tables: it.tables,
|
tables: it.tables,
|
||||||
@@ -197,10 +198,10 @@ impl From<ArchivableModuleInfo> for ModuleInfo {
|
|||||||
exports: it.exports.into(),
|
exports: it.exports.into(),
|
||||||
start_function: it.start_function,
|
start_function: it.start_function,
|
||||||
table_initializers: it.table_initializers,
|
table_initializers: it.table_initializers,
|
||||||
passive_elements: it.passive_elements,
|
passive_elements: it.passive_elements.into_iter().collect(),
|
||||||
passive_data: it.passive_data,
|
passive_data: it.passive_data.into_iter().collect(),
|
||||||
global_initializers: it.global_initializers,
|
global_initializers: it.global_initializers,
|
||||||
function_names: it.function_names,
|
function_names: it.function_names.into_iter().collect(),
|
||||||
signatures: it.signatures,
|
signatures: it.signatures,
|
||||||
functions: it.functions,
|
functions: it.functions,
|
||||||
tables: it.tables,
|
tables: it.tables,
|
||||||
@@ -228,20 +229,22 @@ impl Archive for ModuleInfo {
|
|||||||
type Archived = <ArchivableModuleInfo as Archive>::Archived;
|
type Archived = <ArchivableModuleInfo as Archive>::Archived;
|
||||||
type Resolver = <ArchivableModuleInfo as Archive>::Resolver;
|
type Resolver = <ArchivableModuleInfo as Archive>::Resolver;
|
||||||
|
|
||||||
fn resolve(&self, pos: usize, resolver: Self::Resolver, out: &mut MaybeUninit<Self::Archived>) {
|
unsafe fn resolve(&self, pos: usize, resolver: Self::Resolver, out: *mut Self::Archived) {
|
||||||
ArchivableModuleInfo::from(self).resolve(pos, resolver, out)
|
ArchivableModuleInfo::from(self).resolve(pos, resolver, out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "enable-rkyv")]
|
#[cfg(feature = "enable-rkyv")]
|
||||||
impl<S: Serializer + SharedSerializer + ?Sized> RkyvSerialize<S> for ModuleInfo {
|
impl<S: Serializer + SharedSerializeRegistry + ScratchSpace + ?Sized> RkyvSerialize<S>
|
||||||
|
for ModuleInfo
|
||||||
|
{
|
||||||
fn serialize(&self, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
|
fn serialize(&self, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
|
||||||
ArchivableModuleInfo::from(self).serialize(serializer)
|
ArchivableModuleInfo::from(self).serialize(serializer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "enable-rkyv")]
|
#[cfg(feature = "enable-rkyv")]
|
||||||
impl<D: Fallible + ?Sized + SharedDeserializer> RkyvDeserialize<ModuleInfo, D>
|
impl<D: Fallible + ?Sized + SharedDeserializeRegistry> RkyvDeserialize<ModuleInfo, D>
|
||||||
for Archived<ModuleInfo>
|
for Archived<ModuleInfo>
|
||||||
{
|
{
|
||||||
fn deserialize(&self, deserializer: &mut D) -> Result<ModuleInfo, D::Error> {
|
fn deserialize(&self, deserializer: &mut D) -> Result<ModuleInfo, D::Error> {
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ more-asserts = "0.2"
|
|||||||
cfg-if = "1.0"
|
cfg-if = "1.0"
|
||||||
backtrace = "0.3"
|
backtrace = "0.3"
|
||||||
serde = { version = "1.0", features = ["derive", "rc"] }
|
serde = { version = "1.0", features = ["derive", "rc"] }
|
||||||
rkyv = { version = "0.6.1", optional = true}
|
rkyv = { version = "0.7.20", optional = true }
|
||||||
loupe = { version = "0.1", features = ["enable-indexmap"] }
|
loupe = { version = "0.1", features = ["enable-indexmap"] }
|
||||||
|
|
||||||
[target.'cfg(target_os = "windows")'.dependencies]
|
[target.'cfg(target_os = "windows")'.dependencies]
|
||||||
|
|||||||
@@ -99,13 +99,16 @@ cfg_if::cfg_if! {
|
|||||||
unsafe fn thread_stack() -> (usize, usize) {
|
unsafe fn thread_stack() -> (usize, usize) {
|
||||||
let this_thread = libc::pthread_self();
|
let this_thread = libc::pthread_self();
|
||||||
let mut thread_attrs: libc::pthread_attr_t = mem::zeroed();
|
let mut thread_attrs: libc::pthread_attr_t = mem::zeroed();
|
||||||
#[cfg(not(target_os = "freebsd"))]
|
|
||||||
libc::pthread_getattr_np(this_thread, &mut thread_attrs);
|
|
||||||
#[cfg(target_os = "freebsd")]
|
|
||||||
libc::pthread_attr_get_np(this_thread, &mut thread_attrs);
|
|
||||||
let mut stackaddr: *mut libc::c_void = ptr::null_mut();
|
let mut stackaddr: *mut libc::c_void = ptr::null_mut();
|
||||||
let mut stacksize: libc::size_t = 0;
|
let mut stacksize: libc::size_t = 0;
|
||||||
libc::pthread_attr_getstack(&thread_attrs, &mut stackaddr, &mut stacksize);
|
#[cfg(not(target_os = "freebsd"))]
|
||||||
|
let ok = libc::pthread_getattr_np(this_thread, &mut thread_attrs);
|
||||||
|
#[cfg(target_os = "freebsd")]
|
||||||
|
let ok = libc::pthread_attr_get_np(this_thread, &mut thread_attrs);
|
||||||
|
if ok == 0 {
|
||||||
|
libc::pthread_attr_getstack(&thread_attrs, &mut stackaddr, &mut stacksize);
|
||||||
|
libc::pthread_attr_destroy(&mut thread_attrs);
|
||||||
|
}
|
||||||
(stackaddr as usize, stacksize)
|
(stackaddr as usize, stacksize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
1.53
|
1.56
|
||||||
|
|||||||
44
tests/compilers/deterministic.rs
Normal file
44
tests/compilers/deterministic.rs
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
use anyhow::Result;
|
||||||
|
use wasmer::{wat2wasm, Module};
|
||||||
|
|
||||||
|
fn compile_and_compare(wasm: &[u8]) -> Result<()> {
|
||||||
|
let store = Default::default();
|
||||||
|
|
||||||
|
// compile for first time
|
||||||
|
let module = Module::new(&store, wasm)?;
|
||||||
|
let first = module.serialize()?;
|
||||||
|
|
||||||
|
// compile for second time
|
||||||
|
let module = Module::new(&store, wasm)?;
|
||||||
|
let second = module.serialize()?;
|
||||||
|
|
||||||
|
assert!(first == second);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn deterministic_empty() -> Result<()> {
|
||||||
|
let wasm_bytes = wat2wasm(
|
||||||
|
br#"
|
||||||
|
(module)
|
||||||
|
"#,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
compile_and_compare(&wasm_bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn deterministic_table() -> Result<()> {
|
||||||
|
let wasm_bytes = wat2wasm(
|
||||||
|
br#"
|
||||||
|
(module
|
||||||
|
(table 2 funcref)
|
||||||
|
(func $f1)
|
||||||
|
(func $f2)
|
||||||
|
(elem (i32.const 0) $f1 $f2))
|
||||||
|
"#,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
compile_and_compare(&wasm_bytes)
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
extern crate compiler_test_derive;
|
extern crate compiler_test_derive;
|
||||||
|
|
||||||
mod config;
|
mod config;
|
||||||
|
mod deterministic;
|
||||||
mod imports;
|
mod imports;
|
||||||
mod issues;
|
mod issues;
|
||||||
mod metering;
|
mod metering;
|
||||||
|
|||||||
@@ -257,7 +257,9 @@ fn trap_start_function_import(config: crate::Config) -> Result<()> {
|
|||||||
.err()
|
.err()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
match err {
|
match err {
|
||||||
InstantiationError::Link(_) | InstantiationError::HostEnvInitialization(_) => {
|
InstantiationError::Link(_)
|
||||||
|
| InstantiationError::HostEnvInitialization(_)
|
||||||
|
| InstantiationError::CpuFeature(_) => {
|
||||||
panic!("It should be a start error")
|
panic!("It should be a start error")
|
||||||
}
|
}
|
||||||
InstantiationError::Start(err) => {
|
InstantiationError::Start(err) => {
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ cranelift spec::simd::simd_i8x16_arith2
|
|||||||
cranelift spec::simd::simd_int_to_int_extend
|
cranelift spec::simd::simd_int_to_int_extend
|
||||||
|
|
||||||
# Windows doesn't overcommit and fails to allocate 4GB of memory
|
# Windows doesn't overcommit and fails to allocate 4GB of memory
|
||||||
windows wast::wasmer::max_size_of_memory
|
windows wasmer::max_size_of_memory
|
||||||
|
|
||||||
# Frontends
|
# Frontends
|
||||||
|
|
||||||
|
|||||||
@@ -16,19 +16,14 @@ serde = { version = "1.0", features = ["derive", "rc"], optional = true }
|
|||||||
serde_bytes = { version = "0.11", optional = true }
|
serde_bytes = { version = "0.11", optional = true }
|
||||||
bincode = { version = "1.2", optional = true }
|
bincode = { version = "1.2", optional = true }
|
||||||
loupe = "0.1"
|
loupe = "0.1"
|
||||||
|
enumset = "1.0"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
# Enable the `compiler` feature if you want the engine to compile
|
# Enable the `compiler` feature if you want the engine to compile
|
||||||
# and not be only on headless mode.
|
# and not be only on headless mode.
|
||||||
default = ["serialize", "compiler"]
|
default = ["serialize", "compiler"]
|
||||||
compiler = [
|
compiler = ["wasmer-compiler/translator"]
|
||||||
"wasmer-compiler/translator"
|
serialize = ["serde", "serde_bytes", "bincode"]
|
||||||
]
|
|
||||||
serialize = [
|
|
||||||
"serde",
|
|
||||||
"serde_bytes",
|
|
||||||
"bincode"
|
|
||||||
]
|
|
||||||
|
|
||||||
[badges]
|
[badges]
|
||||||
# TODO: publish this crate again and deprecate it
|
# TODO: publish this crate again and deprecate it
|
||||||
|
|||||||
@@ -2,13 +2,14 @@
|
|||||||
//! done as separate steps.
|
//! done as separate steps.
|
||||||
|
|
||||||
use crate::engine::DummyEngine;
|
use crate::engine::DummyEngine;
|
||||||
|
use enumset::EnumSet;
|
||||||
use loupe::MemoryUsage;
|
use loupe::MemoryUsage;
|
||||||
#[cfg(feature = "serialize")]
|
#[cfg(feature = "serialize")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use wasmer_compiler::CompileError;
|
|
||||||
#[cfg(feature = "compiler")]
|
#[cfg(feature = "compiler")]
|
||||||
use wasmer_compiler::ModuleEnvironment;
|
use wasmer_compiler::ModuleEnvironment;
|
||||||
|
use wasmer_compiler::{CompileError, CpuFeature};
|
||||||
use wasmer_engine::{Artifact, DeserializeError, Engine as _, SerializeError, Tunables};
|
use wasmer_engine::{Artifact, DeserializeError, Engine as _, SerializeError, Tunables};
|
||||||
use wasmer_types::entity::{BoxedSlice, PrimaryMap};
|
use wasmer_types::entity::{BoxedSlice, PrimaryMap};
|
||||||
use wasmer_types::{
|
use wasmer_types::{
|
||||||
@@ -30,6 +31,7 @@ pub struct DummyArtifactMetadata {
|
|||||||
// Plans for that module
|
// Plans for that module
|
||||||
pub memory_styles: PrimaryMap<MemoryIndex, MemoryStyle>,
|
pub memory_styles: PrimaryMap<MemoryIndex, MemoryStyle>,
|
||||||
pub table_styles: PrimaryMap<TableIndex, TableStyle>,
|
pub table_styles: PrimaryMap<TableIndex, TableStyle>,
|
||||||
|
pub cpu_features: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A Dummy artifact.
|
/// A Dummy artifact.
|
||||||
@@ -104,6 +106,7 @@ impl DummyArtifact {
|
|||||||
data_initializers,
|
data_initializers,
|
||||||
memory_styles,
|
memory_styles,
|
||||||
table_styles,
|
table_styles,
|
||||||
|
cpu_features: engine.target().cpu_features().as_u64(),
|
||||||
};
|
};
|
||||||
Self::from_parts(&engine, metadata)
|
Self::from_parts(&engine, metadata)
|
||||||
}
|
}
|
||||||
@@ -211,6 +214,10 @@ impl Artifact for DummyArtifact {
|
|||||||
&self.metadata.features
|
&self.metadata.features
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn cpu_features(&self) -> EnumSet<CpuFeature> {
|
||||||
|
EnumSet::from_u64(self.metadata.cpu_features)
|
||||||
|
}
|
||||||
|
|
||||||
fn data_initializers(&self) -> &[OwnedDataInitializer] {
|
fn data_initializers(&self) -> &[OwnedDataInitializer] {
|
||||||
&*self.metadata.data_initializers
|
&*self.metadata.data_initializers
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user