Merge remote-tracking branch 'origin/master' into wasix

This commit is contained in:
Christoph Herzog
2023-02-02 19:23:13 +01:00
16 changed files with 458 additions and 364 deletions

View File

@@ -102,6 +102,11 @@ jobs:
with: with:
toolchain: 1.64 toolchain: 1.64
target: ${{ matrix.target }} target: ${{ matrix.target }}
- name: Install Rust nightly (to build capi-headless)
uses: dtolnay/rust-toolchain@stable
with:
toolchain: nightly
target: ${{ matrix.metadata.target }}
- uses: Swatinem/rust-cache@v1 - uses: Swatinem/rust-cache@v1
if: matrix.use_sccache != true if: matrix.use_sccache != true
- name: Install LLVM (macOS Apple Silicon) - name: Install LLVM (macOS Apple Silicon)
@@ -273,6 +278,11 @@ jobs:
- uses: dtolnay/rust-toolchain@stable - uses: dtolnay/rust-toolchain@stable
with: with:
target: x86_64-pc-windows-gnu target: x86_64-pc-windows-gnu
- name: Install Rust nightly (to build capi-headless)
uses: dtolnay/rust-toolchain@stable
with:
toolchain: nightly
target: x86_64-pc-windows-gnu
- name: Install Windows-GNU target - name: Install Windows-GNU target
shell: bash shell: bash
run: | run: |
@@ -301,9 +311,19 @@ jobs:
- name: Build Wasmer C-API without LLVM - name: Build Wasmer C-API without LLVM
shell: bash shell: bash
run: | run: |
cargo build --release --target x86_64-pc-windows-gnu --manifest-path lib/c-api/Cargo.toml --no-default-features --features wat,compiler,wasi,middlewares,webc_runner --features cranelift,singlepass,wasmer-artifact-create,static-artifact-create,wasmer-artifact-load,static-artifact-load make build-capi
env: env:
RUSTFLAGS: -Cpanic=abort RUSTFLAGS: -Cpanic=abort
CARGO_TARGET: x86_64-pc-windows-gnu
ENABLE_LLVM: 0
- name: Build Wasmer C-API headless without LLVM
shell: bash
run: |
make build-capi-headless
env:
RUSTFLAGS: -Cpanic=abort
CARGO_TARGET: x86_64-pc-windows-gnu
ENABLE_LLVM: 0
- name: Dist - name: Dist
run: | run: |
make distribution-gnu make distribution-gnu

View File

@@ -263,6 +263,11 @@ jobs:
with: with:
toolchain: 1.64 toolchain: 1.64
target: ${{ matrix.metadata.target }} target: ${{ matrix.metadata.target }}
- name: Install Rust nightly (to build capi-headless)
uses: dtolnay/rust-toolchain@stable
with:
toolchain: nightly
target: ${{ matrix.metadata.target }}
- name: Install Windows-GNU linker - name: Install Windows-GNU linker
if: ${{ matrix.metadata.build == 'windows-gnu' }} if: ${{ matrix.metadata.build == 'windows-gnu' }}
shell: bash shell: bash

556
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -361,7 +361,7 @@ endif
# Not really "all", just the default target that builds enough so make # Not really "all", just the default target that builds enough so make
# install will go through. # install will go through.
all: build-wasmer build-capi all: build-wasmer build-capi build-capi-headless
check: check-wasmer check-wasmer-wasm check-capi check: check-wasmer check-wasmer-wasm check-capi
@@ -565,10 +565,10 @@ test-wasi-unit:
test-wasi: test-wasi:
$(CARGO_BINARY) test $(CARGO_TARGET_FLAG) --release --tests $(compiler_features) -- wasi::wasitests $(CARGO_BINARY) test $(CARGO_TARGET_FLAG) --release --tests $(compiler_features) -- wasi::wasitests
test-integration-cli: build-wasmer build-capi package distribution test-integration-cli: build-wasmer build-capi package-capi-headless package distribution
cp ./dist/wasmer.tar.gz ./link.tar.gz cp ./dist/wasmer.tar.gz ./link.tar.gz
rustup target add wasm32-wasi rustup target add wasm32-wasi
$(CARGO_BINARY) test $(CARGO_TARGET_FLAG) --features webc_runner --no-fail-fast -p wasmer-integration-tests-cli -- --nocapture --test-threads=1 WASMER_DIR=`pwd`/package $(CARGO_BINARY) test $(CARGO_TARGET_FLAG) --features webc_runner --no-fail-fast -p wasmer-integration-tests-cli -- --nocapture --test-threads=1
# Before running this in the CI, we need to set up link.tar.gz and /cache/wasmer-[target].tar.gz # Before running this in the CI, we need to set up link.tar.gz and /cache/wasmer-[target].tar.gz
test-integration-cli-ci: test-integration-cli-ci:
@@ -621,6 +621,8 @@ ifeq ($(IS_DARWIN), 1)
endif endif
endif endif
package-capi-headless: build-capi-headless package-capi
package-capi: package-capi:
mkdir -p "package/include" mkdir -p "package/include"
mkdir -p "package/lib" mkdir -p "package/lib"
@@ -637,6 +639,10 @@ package-capi:
cp target/headless/$(CARGO_TARGET)/release/wasmer.dll package/lib/wasmer-headless.dll ;\ cp target/headless/$(CARGO_TARGET)/release/wasmer.dll package/lib/wasmer-headless.dll ;\
fi fi
if [ -f target/headless/$(HOST_TARGET)/release/wasmer.dll ]; then \
cp target/headless/$(HOST_TARGET)/release/wasmer.dll package/lib/wasmer-headless.dll ;\
fi
if [ -f $(TARGET_DIR)/wasmer.dll.lib ]; then \ if [ -f $(TARGET_DIR)/wasmer.dll.lib ]; then \
cp $(TARGET_DIR)/wasmer.dll.lib package/lib/wasmer.dll.lib ;\ cp $(TARGET_DIR)/wasmer.dll.lib package/lib/wasmer.dll.lib ;\
fi fi
@@ -645,6 +651,10 @@ package-capi:
cp target/headless/$(CARGO_TARGET)/release/wasmer.dll.lib package/lib/wasmer-headless.dll.lib ;\ cp target/headless/$(CARGO_TARGET)/release/wasmer.dll.lib package/lib/wasmer-headless.dll.lib ;\
fi fi
if [ -f target/headless/$(HOST_TARGET)/release/wasmer.dll.lib ]; then \
cp target/headless/$(HOST_TARGET)/release/wasmer.dll.lib package/lib/wasmer-headless.dll.lib ;\
fi
if [ -f $(TARGET_DIR)/wasmer.lib ]; then \ if [ -f $(TARGET_DIR)/wasmer.lib ]; then \
cp $(TARGET_DIR)/wasmer.lib package/lib/wasmer.lib ;\ cp $(TARGET_DIR)/wasmer.lib package/lib/wasmer.lib ;\
fi fi
@@ -653,6 +663,10 @@ package-capi:
cp target/headless/$(CARGO_TARGET)/release/wasmer.lib package/lib/wasmer-headless.lib ;\ cp target/headless/$(CARGO_TARGET)/release/wasmer.lib package/lib/wasmer-headless.lib ;\
fi fi
if [ -f target/headless/$(HOST_TARGET)/release/wasmer.lib ]; then \
cp target/headless/$(HOST_TARGET)/release/wasmer.lib package/lib/wasmer-headless.lib ;\
fi
if [ -f $(TARGET_DIR)/libwasmer.dylib ]; then \ if [ -f $(TARGET_DIR)/libwasmer.dylib ]; then \
cp $(TARGET_DIR)/libwasmer.dylib package/lib/libwasmer.dylib ;\ cp $(TARGET_DIR)/libwasmer.dylib package/lib/libwasmer.dylib ;\
fi fi
@@ -661,6 +675,10 @@ package-capi:
cp target/headless/$(CARGO_TARGET)/release/libwasmer.dylib package/lib/libwasmer-headless.dylib ;\ cp target/headless/$(CARGO_TARGET)/release/libwasmer.dylib package/lib/libwasmer-headless.dylib ;\
fi fi
if [ -f target/headless/$(HOST_TARGET)/release/libwasmer.dylib ]; then \
cp target/headless/$(HOST_TARGET)/release/libwasmer.dylib package/lib/libwasmer-headless.dylib ;\
fi
if [ -f $(TARGET_DIR)/libwasmer.so ]; then \ if [ -f $(TARGET_DIR)/libwasmer.so ]; then \
cp $(TARGET_DIR)/libwasmer.so package/lib/libwasmer.so ;\ cp $(TARGET_DIR)/libwasmer.so package/lib/libwasmer.so ;\
fi fi
@@ -669,6 +687,10 @@ package-capi:
cp target/headless/$(CARGO_TARGET)/release/libwasmer.so package/lib/libwasmer-headless.so ;\ cp target/headless/$(CARGO_TARGET)/release/libwasmer.so package/lib/libwasmer-headless.so ;\
fi fi
if [ -f target/headless/$(HOST_TARGET)/release/libwasmer.so ]; then \
cp target/headless/$(HOST_TARGET)/release/libwasmer.so package/lib/libwasmer-headless.so ;\
fi
if [ -f $(TARGET_DIR)/libwasmer.a ]; then \ if [ -f $(TARGET_DIR)/libwasmer.a ]; then \
cp $(TARGET_DIR)/libwasmer.a package/lib/libwasmer.a ;\ cp $(TARGET_DIR)/libwasmer.a package/lib/libwasmer.a ;\
fi fi
@@ -677,6 +699,10 @@ package-capi:
cp target/headless/$(CARGO_TARGET)/release/libwasmer.a package/lib/libwasmer-headless.a ;\ cp target/headless/$(CARGO_TARGET)/release/libwasmer.a package/lib/libwasmer-headless.a ;\
fi fi
if [ -f target/headless/$(HOST_TARGET)/release/libwasmer.a ]; then \
cp target/headless/$(HOST_TARGET)/release/libwasmer.a package/lib/libwasmer-headless.a ;\
fi
if [ -f target/$(HOST_TARGET)/release/wasmer.dll ]; then \ if [ -f target/$(HOST_TARGET)/release/wasmer.dll ]; then \
cp target/$(HOST_TARGET)/release/wasmer.dll package/lib/wasmer.dll ;\ cp target/$(HOST_TARGET)/release/wasmer.dll package/lib/wasmer.dll ;\
fi fi
@@ -699,39 +725,13 @@ package-capi:
cp target/$(HOST_TARGET)/release/libwasmer.a package/lib/libwasmer.a ;\ cp target/$(HOST_TARGET)/release/libwasmer.a package/lib/libwasmer.a ;\
fi fi
package-capi-headless: build-capi-headless
mkdir -p "package/include"
mkdir -p "package/lib"
cp lib/c-api/wasmer.h* package/include
cp lib/c-api/wasmer_wasm.h* package/include
cp lib/c-api/wasm.h* package/include
cp lib/c-api/README.md package/include/README.md
if [ -f $(TARGET_DIR)/wasmer.dll ]; then \
cp $(TARGET_DIR)/wasmer.dll package/lib/wasmer-headless.dll ;\
fi
if [ -f $(TARGET_DIR)/wasmer.lib ]; then \
cp $(TARGET_DIR)/wasmer.lib package/lib/wasmer-headless.lib ;\
fi
if [ -f $(TARGET_DIR)/libwasmer.dylib ]; then \
cp $(TARGET_DIR)/libwasmer.dylib package/lib/libwasmer-headless.dylib ;\
fi
if [ -f $(TARGET_DIR)/libwasmer.so ]; then \
cp $(TARGET_DIR)/libwasmer.so package/lib/libwasmer-headless.so ;\
fi
if [ -f $(TARGET_DIR)/libwasmer.a ]; then \
cp $(TARGET_DIR)/libwasmer.a package/lib/libwasmer-headless.a ;\
fi
package-docs: build-docs build-docs-capi package-docs: build-docs build-docs-capi
mkdir -p "package/docs/crates" mkdir -p "package/docs/crates"
cp -R target/doc/ package/docs/crates cp -R target/doc/ package/docs/crates
echo '<meta http-equiv="refresh" content="0; url=crates/wasmer/index.html">' > package/docs/index.html echo '<meta http-equiv="refresh" content="0; url=crates/wasmer/index.html">' > package/docs/index.html
echo '<meta http-equiv="refresh" content="0; url=wasmer/index.html">' > package/docs/crates/index.html echo '<meta http-equiv="refresh" content="0; url=wasmer/index.html">' > package/docs/crates/index.html
package: package-wasmer package-minimal-headless-wasmer package-capi package-capi-headless package: package-wasmer package-minimal-headless-wasmer package-capi
tar-capi: tar-capi:
ls -R package ls -R package

View File

@@ -33,7 +33,7 @@ impl Login {
registry_tld.suffix.as_deref(), registry_tld.suffix.as_deref(),
) { ) {
(Some(d), Some(s)) => { (Some(d), Some(s)) => {
format!("Please paste the login token for https://{d}.{s}/me") format!("Please paste the login token from https://{d}.{s}/settings/access-tokens")
} }
_ => "Please paste the login token".to_string(), _ => "Please paste the login token".to_string(),
}; };

View File

@@ -14,9 +14,9 @@ edition = "2018"
[dependencies] [dependencies]
wasmer-compiler = { path = "../compiler", version = "=3.2.0-alpha.1", features = ["translator", "compiler"], default-features = false } wasmer-compiler = { path = "../compiler", version = "=3.2.0-alpha.1", features = ["translator", "compiler"], default-features = false }
wasmer-types = { path = "../types", version = "=3.2.0-alpha.1", default-features = false, features = ["std"] } wasmer-types = { path = "../types", version = "=3.2.0-alpha.1", default-features = false, features = ["std"] }
cranelift-entity = { version = "0.86.1", default-features = false } cranelift-entity = { version = "0.91.0", default-features = false }
cranelift-codegen = { version = "0.86.1", default-features = false, features = ["x86", "arm64"] } cranelift-codegen = { version = "0.91.0", default-features = false, features = ["x86", "arm64"] }
cranelift-frontend = { version = "0.86.1", default-features = false } cranelift-frontend = { version = "0.91.0", default-features = false }
tracing = "0.1" tracing = "0.1"
hashbrown = { version = "0.11", optional = true } hashbrown = { version = "0.11", optional = true }
rayon = { version = "1.5", optional = true } rayon = { version = "1.5", optional = true }
@@ -26,7 +26,7 @@ smallvec = "1.6"
target-lexicon = { version = "0.12.2", default-features = false } target-lexicon = { version = "0.12.2", default-features = false }
[dev-dependencies] [dev-dependencies]
cranelift-codegen = { version = "0.86.1", features = ["all-arch"] } cranelift-codegen = { version = "0.91.0", features = ["all-arch"] }
lazy_static = "1.4" lazy_static = "1.4"
[badges] [badges]

View File

@@ -15,7 +15,7 @@ pub fn get_function_address_map(
// New-style backend: we have a `MachCompileResult` that will give us `MachSrcLoc` mapping // New-style backend: we have a `MachCompileResult` that will give us `MachSrcLoc` mapping
// tuples. // tuples.
let mcr = context.mach_compile_result.as_ref().unwrap(); let mcr = context.compiled_code().unwrap();
for &MachSrcLoc { start, end, loc } in mcr.buffer.get_srclocs_sorted() { for &MachSrcLoc { start, end, loc } in mcr.buffer.get_srclocs_sorted() {
instructions.push(InstructionAddressMap { instructions.push(InstructionAddressMap {
srcloc: SourceLoc::new(loc.bits()), srcloc: SourceLoc::new(loc.bits()),

View File

@@ -12,8 +12,7 @@ use crate::translator::{
compiled_function_unwind_info, irlibcall_to_libcall, irreloc_to_relocationkind, compiled_function_unwind_info, irlibcall_to_libcall, irreloc_to_relocationkind,
signature_to_cranelift_ir, CraneliftUnwindInfo, FuncTranslator, signature_to_cranelift_ir, CraneliftUnwindInfo, FuncTranslator,
}; };
use cranelift_codegen::ir::ExternalName; use cranelift_codegen::ir::{ExternalName, UserFuncName};
use cranelift_codegen::print_errors::pretty_error;
use cranelift_codegen::{ir, MachReloc}; use cranelift_codegen::{ir, MachReloc};
use cranelift_codegen::{Context, MachTrap}; use cranelift_codegen::{Context, MachTrap};
#[cfg(feature = "unwind")] #[cfg(feature = "unwind")]
@@ -127,7 +126,18 @@ impl Compiler for CraneliftCompiler {
&memory_styles, &memory_styles,
&table_styles, &table_styles,
); );
context.func.name = get_function_name(func_index); context.func.name = match get_function_name(func_index) {
ExternalName::User(nameref) => {
if context.func.params.user_named_funcs().is_valid(nameref) {
let name = &context.func.params.user_named_funcs()[nameref];
UserFuncName::User(name.clone())
} else {
UserFuncName::default()
}
}
ExternalName::TestCase(testcase) => UserFuncName::Testcase(testcase),
_ => UserFuncName::default(),
};
context.func.signature = signatures[module.functions[func_index]].clone(); context.func.signature = signatures[module.functions[func_index]].clone();
// if generate_debug_info { // if generate_debug_info {
// context.func.collect_debug_info(); // context.func.collect_debug_info();
@@ -151,9 +161,9 @@ impl Compiler for CraneliftCompiler {
let mut code_buf: Vec<u8> = Vec::new(); let mut code_buf: Vec<u8> = Vec::new();
context context
.compile_and_emit(&*isa, &mut code_buf) .compile_and_emit(&*isa, &mut code_buf)
.map_err(|error| CompileError::Codegen(pretty_error(&context.func, error)))?; .map_err(|error| CompileError::Codegen(error.inner.to_string()))?;
let result = context.mach_compile_result.as_ref().unwrap(); let result = context.compiled_code().unwrap();
let func_relocs = result let func_relocs = result
.buffer .buffer
.relocs() .relocs()
@@ -228,7 +238,18 @@ impl Compiler for CraneliftCompiler {
memory_styles, memory_styles,
table_styles, table_styles,
); );
context.func.name = get_function_name(func_index); context.func.name = match get_function_name(func_index) {
ExternalName::User(nameref) => {
if context.func.params.user_named_funcs().is_valid(nameref) {
let name = &context.func.params.user_named_funcs()[nameref];
UserFuncName::User(name.clone())
} else {
UserFuncName::default()
}
}
ExternalName::TestCase(testcase) => UserFuncName::Testcase(testcase),
_ => UserFuncName::default(),
};
context.func.signature = signatures[module.functions[func_index]].clone(); context.func.signature = signatures[module.functions[func_index]].clone();
// if generate_debug_info { // if generate_debug_info {
// context.func.collect_debug_info(); // context.func.collect_debug_info();
@@ -252,9 +273,9 @@ impl Compiler for CraneliftCompiler {
let mut code_buf: Vec<u8> = Vec::new(); let mut code_buf: Vec<u8> = Vec::new();
context context
.compile_and_emit(&*isa, &mut code_buf) .compile_and_emit(&*isa, &mut code_buf)
.map_err(|error| CompileError::Codegen(pretty_error(&context.func, error)))?; .map_err(|error| CompileError::Codegen(error.inner.to_string()))?;
let result = context.mach_compile_result.as_ref().unwrap(); let result = context.compiled_code().unwrap();
let func_relocs = result let func_relocs = result
.buffer .buffer
.relocs() .relocs()
@@ -401,11 +422,11 @@ fn mach_reloc_to_reloc(module: &ModuleInfo, reloc: &MachReloc) -> Relocation {
ref name, ref name,
addend, addend,
} = reloc; } = reloc;
let reloc_target = if let ExternalName::User { namespace, index } = *name { let reloc_target = if let ExternalName::User(extname_ref) = *name {
debug_assert_eq!(namespace, 0); //debug_assert_eq!(namespace, 0);
RelocationTarget::LocalFunc( RelocationTarget::LocalFunc(
module module
.local_func_index(FunctionIndex::from_u32(index)) .local_func_index(FunctionIndex::from_u32(extname_ref.as_u32()))
.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 {

View File

@@ -124,6 +124,11 @@ impl Cranelift {
pub fn flags(&self) -> settings::Flags { pub fn flags(&self) -> settings::Flags {
let mut flags = settings::builder(); let mut flags = settings::builder();
// Enable probestack
flags
.enable("enable_probestack")
.expect("should be valid flag");
// There are two possible traps for division, and this way // There are two possible traps for division, and this way
// we get the proper one if code traps. // we get the proper one if code traps.
flags flags

View File

@@ -27,7 +27,7 @@ use wasmer_types::{WasmError, WasmResult};
/// Compute an `ir::ExternalName` for a given wasm function index. /// Compute an `ir::ExternalName` for a given wasm function index.
pub fn get_function_name(func_index: FunctionIndex) -> ir::ExternalName { pub fn get_function_name(func_index: FunctionIndex) -> ir::ExternalName {
ir::ExternalName::user(0, func_index.as_u32()) ir::ExternalName::user(ir::UserExternalNameRef::from_u32(func_index.as_u32()))
} }
/// The type of the `current_elements` field. /// The type of the `current_elements` field.
@@ -1028,7 +1028,7 @@ impl<'module_environment> BaseFuncEnvironment for FuncEnvironment<'module_enviro
_ => unreachable!(), _ => unreachable!(),
}; };
Ok(pos.ins().bint(ir::types::I32, bool_is_null)) Ok(pos.ins().uextend(ir::types::I32, bool_is_null))
} }
fn translate_ref_func( fn translate_ref_func(

View File

@@ -6,10 +6,9 @@
use crate::translator::{compiled_function_unwind_info, signature_to_cranelift_ir}; use crate::translator::{compiled_function_unwind_info, signature_to_cranelift_ir};
use cranelift_codegen::ir; use cranelift_codegen::ir;
use cranelift_codegen::ir::{ use cranelift_codegen::ir::{
ExternalName, Function, InstBuilder, MemFlags, StackSlotData, StackSlotKind, Function, InstBuilder, MemFlags, StackSlotData, StackSlotKind, UserFuncName,
}; };
use cranelift_codegen::isa::TargetIsa; use cranelift_codegen::isa::TargetIsa;
use cranelift_codegen::print_errors::pretty_error;
use cranelift_codegen::Context; use cranelift_codegen::Context;
use std::cmp; use std::cmp;
use std::mem; use std::mem;
@@ -43,9 +42,9 @@ pub fn make_trampoline_dynamic_function(
(value_size * cmp::max(signature.params.len() - 1, signature.returns.len())) as u32; (value_size * cmp::max(signature.params.len() - 1, signature.returns.len())) as u32;
let mut context = Context::new(); let mut context = Context::new();
context.func = Function::with_name_signature(ExternalName::user(0, 0), signature.clone()); context.func = Function::with_name_signature(UserFuncName::user(0, 0), signature.clone());
let ss = context.func.create_stack_slot(StackSlotData::new( let ss = context.func.create_sized_stack_slot(StackSlotData::new(
StackSlotKind::ExplicitSlot, StackSlotKind::ExplicitSlot,
values_vec_len, values_vec_len,
)); ));
@@ -107,7 +106,7 @@ pub fn make_trampoline_dynamic_function(
let mut code_buf = Vec::new(); let mut code_buf = Vec::new();
context context
.compile_and_emit(isa, &mut code_buf) .compile_and_emit(isa, &mut code_buf)
.map_err(|error| CompileError::Codegen(pretty_error(&context.func, error)))?; .map_err(|error| CompileError::Codegen(error.inner.to_string()))?;
let unwind_info = compiled_function_unwind_info(isa, &context)?.maybe_into_to_windows_unwind(); let unwind_info = compiled_function_unwind_info(isa, &context)?.maybe_into_to_windows_unwind();

View File

@@ -12,7 +12,6 @@ use crate::translator::{compiled_function_unwind_info, signature_to_cranelift_ir
use cranelift_codegen::ir; use cranelift_codegen::ir;
use cranelift_codegen::ir::InstBuilder; use cranelift_codegen::ir::InstBuilder;
use cranelift_codegen::isa::TargetIsa; use cranelift_codegen::isa::TargetIsa;
use cranelift_codegen::print_errors::pretty_error;
use cranelift_codegen::Context; use cranelift_codegen::Context;
use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext}; use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
use std::mem; use std::mem;
@@ -42,7 +41,7 @@ pub fn make_trampoline_function_call(
wrapper_sig.params.push(ir::AbiParam::new(pointer_type)); wrapper_sig.params.push(ir::AbiParam::new(pointer_type));
let mut context = Context::new(); let mut context = Context::new();
context.func = ir::Function::with_name_signature(ir::ExternalName::user(0, 0), wrapper_sig); context.func = ir::Function::with_name_signature(ir::UserFuncName::user(0, 0), wrapper_sig);
let value_size = mem::size_of::<u128>(); let value_size = mem::size_of::<u128>();
{ {
@@ -105,7 +104,7 @@ pub fn make_trampoline_function_call(
context context
.compile_and_emit(isa, &mut code_buf) .compile_and_emit(isa, &mut code_buf)
.map_err(|error| CompileError::Codegen(pretty_error(&context.func, error)))?; .map_err(|error| CompileError::Codegen(error.inner.to_string()))?;
let unwind_info = compiled_function_unwind_info(isa, &context)?.maybe_into_to_windows_unwind(); let unwind_info = compiled_function_unwind_info(isa, &context)?.maybe_into_to_windows_unwind();

View File

@@ -124,7 +124,7 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
* disappear in the Cranelift Code * disappear in the Cranelift Code
***********************************************************************************/ ***********************************************************************************/
Operator::LocalGet { local_index } => { Operator::LocalGet { local_index } => {
let val = builder.use_var(Variable::with_u32(*local_index)); let val = builder.use_var(Variable::from_u32(*local_index));
state.push1(val); state.push1(val);
let label = ValueLabel::from_u32(*local_index); let label = ValueLabel::from_u32(*local_index);
builder.set_val_label(val, label); builder.set_val_label(val, label);
@@ -138,7 +138,7 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
val = optionally_bitcast_vector(val, I8X16, builder); val = optionally_bitcast_vector(val, I8X16, builder);
} }
builder.def_var(Variable::with_u32(*local_index), val); builder.def_var(Variable::from_u32(*local_index), val);
let label = ValueLabel::from_u32(*local_index); let label = ValueLabel::from_u32(*local_index);
builder.set_val_label(val, label); builder.set_val_label(val, label);
} }
@@ -151,7 +151,7 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
val = optionally_bitcast_vector(val, I8X16, builder); val = optionally_bitcast_vector(val, I8X16, builder);
} }
builder.def_var(Variable::with_u32(*local_index), val); builder.def_var(Variable::from_u32(*local_index), val);
let label = ValueLabel::from_u32(*local_index); let label = ValueLabel::from_u32(*local_index);
builder.set_val_label(val, label); builder.set_val_label(val, label);
} }
@@ -368,8 +368,7 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
Operator::End => { Operator::End => {
let frame = state.control_stack.pop().unwrap(); let frame = state.control_stack.pop().unwrap();
let next_block = frame.following_code(); let next_block = frame.following_code();
if !builder.is_unreachable() || builder.func.layout.first_inst(next_block).is_some() {
if !builder.is_unreachable() || !builder.is_pristine() {
let return_count = frame.num_return_values(); let return_count = frame.num_return_values();
let return_args = state.peekn(return_count); let return_args = state.peekn(return_count);
canonicalise_then_jump(builder, frame.following_code(), return_args); canonicalise_then_jump(builder, frame.following_code(), return_args);
@@ -519,11 +518,8 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
state.reachable = false; state.reachable = false;
} }
Operator::Return => { Operator::Return => {
let (return_count, br_destination) = { let (return_count, _br_destination) = {
let frame = &mut state.control_stack[0]; let frame = &mut state.control_stack[0];
if environ.return_mode() == ReturnMode::FallthroughReturn {
frame.set_branched_to_exit();
}
let return_count = frame.num_return_values(); let return_count = frame.num_return_values();
(return_count, frame.br_destination()) (return_count, frame.br_destination())
}; };
@@ -536,9 +532,6 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
bitcast_arguments(return_args, &return_types, builder); bitcast_arguments(return_args, &return_types, builder);
match environ.return_mode() { match environ.return_mode() {
ReturnMode::NormalReturns => builder.ins().return_(return_args), ReturnMode::NormalReturns => builder.ins().return_(return_args),
ReturnMode::FallthroughReturn => {
canonicalise_then_jump(builder, br_destination, return_args)
}
}; };
} }
state.popn(return_count); state.popn(return_count);
@@ -861,19 +854,19 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
} }
Operator::F32ReinterpretI32 => { Operator::F32ReinterpretI32 => {
let val = state.pop1(); let val = state.pop1();
state.push1(builder.ins().bitcast(F32, val)); state.push1(builder.ins().bitcast(F32, MemFlags::new(), val));
} }
Operator::F64ReinterpretI64 => { Operator::F64ReinterpretI64 => {
let val = state.pop1(); let val = state.pop1();
state.push1(builder.ins().bitcast(F64, val)); state.push1(builder.ins().bitcast(F64, MemFlags::new(), val));
} }
Operator::I32ReinterpretF32 => { Operator::I32ReinterpretF32 => {
let val = state.pop1(); let val = state.pop1();
state.push1(builder.ins().bitcast(I32, val)); state.push1(builder.ins().bitcast(I32, MemFlags::new(), val));
} }
Operator::I64ReinterpretF64 => { Operator::I64ReinterpretF64 => {
let val = state.pop1(); let val = state.pop1();
state.push1(builder.ins().bitcast(I64, val)); state.push1(builder.ins().bitcast(I64, MemFlags::new(), val));
} }
Operator::I32Extend8S => { Operator::I32Extend8S => {
let val = state.pop1(); let val = state.pop1();
@@ -1022,7 +1015,7 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
Operator::I32Eqz | Operator::I64Eqz => { Operator::I32Eqz | Operator::I64Eqz => {
let arg = state.pop1(); let arg = state.pop1();
let val = builder.ins().icmp_imm(IntCC::Equal, arg, 0); let val = builder.ins().icmp_imm(IntCC::Equal, arg, 0);
state.push1(builder.ins().bint(I32, val)); state.push1(builder.ins().uextend(I32, val));
} }
Operator::I32Eq | Operator::I64Eq => translate_icmp(IntCC::Equal, builder, state), Operator::I32Eq | Operator::I64Eq => translate_icmp(IntCC::Equal, builder, state),
Operator::F32Eq | Operator::F64Eq => translate_fcmp(FloatCC::Equal, builder, state), Operator::F32Eq | Operator::F64Eq => translate_fcmp(FloatCC::Equal, builder, state),
@@ -1583,7 +1576,7 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
} }
Operator::I8x16MinS | Operator::I16x8MinS | Operator::I32x4MinS => { Operator::I8x16MinS | Operator::I16x8MinS | Operator::I32x4MinS => {
let (a, b) = pop2_with_bitcast(state, type_of(op), builder); let (a, b) = pop2_with_bitcast(state, type_of(op), builder);
state.push1(builder.ins().imin(a, b)) state.push1(builder.ins().smin(a, b))
} }
Operator::I8x16MinU | Operator::I16x8MinU | Operator::I32x4MinU => { Operator::I8x16MinU | Operator::I16x8MinU | Operator::I32x4MinU => {
let (a, b) = pop2_with_bitcast(state, type_of(op), builder); let (a, b) = pop2_with_bitcast(state, type_of(op), builder);
@@ -1591,7 +1584,7 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
} }
Operator::I8x16MaxS | Operator::I16x8MaxS | Operator::I32x4MaxS => { Operator::I8x16MaxS | Operator::I16x8MaxS | Operator::I32x4MaxS => {
let (a, b) = pop2_with_bitcast(state, type_of(op), builder); let (a, b) = pop2_with_bitcast(state, type_of(op), builder);
state.push1(builder.ins().imax(a, b)) state.push1(builder.ins().smax(a, b))
} }
Operator::I8x16MaxU | Operator::I16x8MaxU | Operator::I32x4MaxU => { Operator::I8x16MaxU | Operator::I16x8MaxU | Operator::I32x4MaxU => {
let (a, b) = pop2_with_bitcast(state, type_of(op), builder); let (a, b) = pop2_with_bitcast(state, type_of(op), builder);
@@ -1672,7 +1665,7 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
Operator::V128AnyTrue => { Operator::V128AnyTrue => {
let a = pop1_with_bitcast(state, type_of(op), builder); let a = pop1_with_bitcast(state, type_of(op), builder);
let bool_result = builder.ins().vany_true(a); let bool_result = builder.ins().vany_true(a);
state.push1(builder.ins().bint(I32, bool_result)) state.push1(builder.ins().uextend(I32, bool_result))
} }
Operator::I8x16AllTrue Operator::I8x16AllTrue
| Operator::I16x8AllTrue | Operator::I16x8AllTrue
@@ -1680,7 +1673,7 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
| Operator::I64x2AllTrue => { | Operator::I64x2AllTrue => {
let a = pop1_with_bitcast(state, type_of(op), builder); let a = pop1_with_bitcast(state, type_of(op), builder);
let bool_result = builder.ins().vall_true(a); let bool_result = builder.ins().vall_true(a);
state.push1(builder.ins().bint(I32, bool_result)) state.push1(builder.ins().uextend(I32, bool_result))
} }
Operator::I8x16Bitmask Operator::I8x16Bitmask
| Operator::I16x8Bitmask | Operator::I16x8Bitmask
@@ -2253,7 +2246,9 @@ fn get_heap_addr(
}; };
debug_assert!(adjusted_offset > 0); // want to bounds check at least 1 byte debug_assert!(adjusted_offset > 0); // want to bounds check at least 1 byte
let check_size = u32::try_from(adjusted_offset).unwrap_or(u32::MAX); let check_size = u32::try_from(adjusted_offset).unwrap_or(u32::MAX);
let base = builder.ins().heap_addr(addr_ty, heap, addr32, check_size); let base = builder
.ins()
.heap_addr(addr_ty, heap, addr32, 0u32, check_size as u8);
// Native load/store instructions take a signed `Offset32` immediate, so adjust the base // Native load/store instructions take a signed `Offset32` immediate, so adjust the base
// pointer if necessary. // pointer if necessary.
@@ -2359,7 +2354,7 @@ fn mem_op_size(opcode: ir::Opcode, ty: Type) -> u32 {
fn translate_icmp(cc: IntCC, builder: &mut FunctionBuilder, state: &mut FuncTranslationState) { fn translate_icmp(cc: IntCC, builder: &mut FunctionBuilder, state: &mut FuncTranslationState) {
let (arg0, arg1) = state.pop2(); let (arg0, arg1) = state.pop2();
let val = builder.ins().icmp(cc, arg0, arg1); let val = builder.ins().icmp(cc, arg0, arg1);
state.push1(builder.ins().bint(I32, val)); state.push1(builder.ins().uextend(I32, val));
} }
fn fold_atomic_mem_addr( fn fold_atomic_mem_addr(
@@ -2375,12 +2370,10 @@ fn fold_atomic_mem_addr(
let a = builder let a = builder
.ins() .ins()
.iadd_imm(linear_mem_addr, memarg.offset as i64); .iadd_imm(linear_mem_addr, memarg.offset as i64);
let cflags = builder.ins().ifcmp_imm(a, 0x1_0000_0000i64); let r = builder
builder.ins().trapif( .ins()
IntCC::UnsignedGreaterThanOrEqual, .icmp_imm(IntCC::UnsignedGreaterThanOrEqual, a, 0x1_0000_0000i64);
cflags, builder.ins().trapnz(r, ir::TrapCode::HeapOutOfBounds);
ir::TrapCode::HeapOutOfBounds,
);
builder.ins().ireduce(I32, a) builder.ins().ireduce(I32, a)
} else { } else {
linear_mem_addr linear_mem_addr
@@ -2391,10 +2384,8 @@ fn fold_atomic_mem_addr(
.band_imm(final_lma, i64::from(access_ty_bytes - 1)); .band_imm(final_lma, i64::from(access_ty_bytes - 1));
let f = builder let f = builder
.ins() .ins()
.ifcmp_imm(final_lma_misalignment, i64::from(0)); .icmp_imm(IntCC::Equal, final_lma_misalignment, i64::from(0));
builder builder.ins().trapz(f, ir::TrapCode::HeapMisaligned);
.ins()
.trapif(IntCC::NotEqual, f, ir::TrapCode::HeapMisaligned);
final_lma final_lma
} }
@@ -2415,12 +2406,10 @@ fn finalise_atomic_mem_addr<FE: FuncEnvironment + ?Sized>(
let a = builder let a = builder
.ins() .ins()
.iadd_imm(linear_mem_addr, memarg.offset as i64); .iadd_imm(linear_mem_addr, memarg.offset as i64);
let cflags = builder.ins().ifcmp_imm(a, 0x1_0000_0000i64); let r = builder
builder.ins().trapif( .ins()
IntCC::UnsignedGreaterThanOrEqual, .icmp_imm(IntCC::UnsignedGreaterThanOrEqual, a, 0x1_0000_0000i64);
cflags, builder.ins().trapnz(r, ir::TrapCode::HeapOutOfBounds);
ir::TrapCode::HeapOutOfBounds,
);
builder.ins().ireduce(I32, a) builder.ins().ireduce(I32, a)
} else { } else {
linear_mem_addr linear_mem_addr
@@ -2433,10 +2422,8 @@ fn finalise_atomic_mem_addr<FE: FuncEnvironment + ?Sized>(
.band_imm(final_lma, i64::from(access_ty_bytes - 1)); .band_imm(final_lma, i64::from(access_ty_bytes - 1));
let f = builder let f = builder
.ins() .ins()
.ifcmp_imm(final_lma_misalignment, i64::from(0)); .icmp_imm(IntCC::Equal, final_lma_misalignment, i64::from(0));
builder builder.ins().trapz(f, ir::TrapCode::HeapMisaligned);
.ins()
.trapif(IntCC::NotEqual, f, ir::TrapCode::HeapMisaligned);
} }
// Compute the final effective address. // Compute the final effective address.
@@ -2647,7 +2634,7 @@ fn translate_vector_icmp(
fn translate_fcmp(cc: FloatCC, builder: &mut FunctionBuilder, state: &mut FuncTranslationState) { fn translate_fcmp(cc: FloatCC, builder: &mut FunctionBuilder, state: &mut FuncTranslationState) {
let (arg0, arg1) = state.pop2(); let (arg0, arg1) = state.pop2();
let val = builder.ins().fcmp(cc, arg0, arg1); let val = builder.ins().fcmp(cc, arg0, arg1);
state.push1(builder.ins().bint(I32, val)); state.push1(builder.ins().uextend(I32, val));
} }
fn translate_vector_fcmp( fn translate_vector_fcmp(
@@ -2913,7 +2900,11 @@ fn optionally_bitcast_vector(
builder: &mut FunctionBuilder, builder: &mut FunctionBuilder,
) -> Value { ) -> Value {
if builder.func.dfg.value_type(value) != needed_type { if builder.func.dfg.value_type(value) != needed_type {
builder.ins().raw_bitcast(needed_type, value) builder.ins().bitcast(
needed_type,
MemFlags::new().with_endianness(ir::Endianness::Little),
value,
)
} else { } else {
value value
} }
@@ -2921,10 +2912,7 @@ fn optionally_bitcast_vector(
#[inline(always)] #[inline(always)]
fn is_non_canonical_v128(ty: ir::Type) -> bool { fn is_non_canonical_v128(ty: ir::Type) -> bool {
matches!( matches!(ty, I64X2 | I32X4 | I16X8 | F32X4 | F64X2)
ty,
B8X16 | B16X8 | B32X4 | B64X2 | I64X2 | I32X4 | I16X8 | F32X4 | F64X2
)
} }
/// Cast to I8X16, any vector values in `values` that are of "non-canonical" type (meaning, not /// Cast to I8X16, any vector values in `values` that are of "non-canonical" type (meaning, not
@@ -2948,7 +2936,11 @@ fn canonicalise_v128_values<'a>(
// Otherwise we'll have to cast, and push the resulting `Value`s into `canonicalised`. // Otherwise we'll have to cast, and push the resulting `Value`s into `canonicalised`.
for v in values { for v in values {
tmp_canonicalised.push(if is_non_canonical_v128(builder.func.dfg.value_type(*v)) { tmp_canonicalised.push(if is_non_canonical_v128(builder.func.dfg.value_type(*v)) {
builder.ins().raw_bitcast(I8X16, *v) builder.ins().bitcast(
I8X16,
MemFlags::new().with_endianness(ir::Endianness::Little),
*v,
)
} else { } else {
*v *v
}); });

View File

@@ -46,8 +46,6 @@ pub enum GlobalVariable {
pub enum ReturnMode { pub enum ReturnMode {
/// Use normal return instructions as needed. /// Use normal return instructions as needed.
NormalReturns, NormalReturns,
/// Use a single fallthrough return at the end of the function.
FallthroughReturn,
} }
/// Environment affecting the translation of a WebAssembly. /// Environment affecting the translation of a WebAssembly.
@@ -381,7 +379,7 @@ pub trait FuncEnvironment: TargetEnvironment {
value: ir::Value, value: ir::Value,
) -> WasmResult<ir::Value> { ) -> WasmResult<ir::Value> {
let is_null = pos.ins().is_null(value); let is_null = pos.ins().is_null(value);
Ok(pos.ins().bint(ir::types::I64, is_null)) Ok(pos.ins().uextend(ir::types::I64, is_null))
} }
/// Translate a `ref.func` WebAssembly instruction. /// Translate a `ref.func` WebAssembly instruction.

View File

@@ -243,7 +243,7 @@ fn parse_function_body<FE: FuncEnvironment + ?Sized>(
// If the exit block is unreachable, it may not have the correct arguments, so we would // If the exit block is unreachable, it may not have the correct arguments, so we would
// generate a return instruction that doesn't match the signature. // generate a return instruction that doesn't match the signature.
if state.reachable { if state.reachable {
debug_assert!(builder.is_pristine()); //debug_assert!(builder.is_pristine());
if !builder.is_unreachable() { if !builder.is_unreachable() {
match environ.return_mode() { match environ.return_mode() {
ReturnMode::NormalReturns => { ReturnMode::NormalReturns => {
@@ -253,7 +253,6 @@ fn parse_function_body<FE: FuncEnvironment + ?Sized>(
bitcast_arguments(&mut state.stack, &return_types, builder); bitcast_arguments(&mut state.stack, &return_types, builder);
builder.ins().return_(&state.stack) builder.ins().return_(&state.stack)
} }
ReturnMode::FallthroughReturn => builder.ins().fallthrough_return(&state.stack),
}; };
} }
} }

View File

@@ -43,6 +43,8 @@ pub(crate) fn compiled_function_unwind_info(
context: &Context, context: &Context,
) -> Result<CraneliftUnwindInfo, CompileError> { ) -> Result<CraneliftUnwindInfo, CompileError> {
let unwind_info = context let unwind_info = context
.compiled_code()
.unwrap()
.create_unwind_info(isa) .create_unwind_info(isa)
.map_err(|error| CompileError::Codegen(pretty_error(&context.func, error)))?; .map_err(|error| CompileError::Codegen(pretty_error(&context.func, error)))?;