diff --git a/Cargo.lock b/Cargo.lock index 97ee9246457..4093f046f66 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -375,18 +375,18 @@ checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" [[package]] name = "cranelift-bforest" -version = "0.70.0" +version = "0.73.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f782ffb172d8095cbb4c6464d85432c3bcfa8609b0bb1dc27cfd35bd90e052" +checksum = "07f641ec9146b7d7498d78cd832007d66ca44a9b61f23474d1fb78e5a3701e99" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.70.0" +version = "0.73.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e0910022b490bd0a65d5baa1693b0475cdbeea1c26472343f2acea1f1f55b8" +checksum = "fd1f2c0cd4ac12c954116ab2e26e40df0d51db322a855b5664fa208bc32d6686" dependencies = [ "byteorder", "cranelift-bforest", @@ -398,15 +398,15 @@ dependencies = [ "log", "regalloc", "smallvec", - "target-lexicon", + "target-lexicon 0.12.0", "thiserror", ] [[package]] name = "cranelift-codegen-meta" -version = "0.70.0" +version = "0.73.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cafe95cb5ac659e113549b2794a2c8d3a14f36e1a98728a6e0ea7a773be2129" +checksum = "105e11b2f0ff7ac81f80dd05ec938ce529a75e36f3d598360d806bb5bfa75e5a" dependencies = [ "cranelift-codegen-shared", "cranelift-entity", @@ -414,27 +414,27 @@ dependencies = [ [[package]] name = "cranelift-codegen-shared" -version = "0.70.0" +version = "0.73.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d1bd002e42cc094a131a8227d06d48df28ea3b9127e5e3bc3010e079858e9af" +checksum = "51e5eba2c1858d50abf023be4d88bd0450cb12d4ec2ba3ffac56353e6d09caf2" [[package]] name = "cranelift-entity" -version = "0.70.0" +version = "0.73.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e55e9043403f0dec775f317280015150e78b2352fb947d2f37407fd4ce6311c7" +checksum = "79fa6fdd77a8d317763cd21668d3e72b96e09ac8a974326c6149f7de5aafa8ed" [[package]] name = "cranelift-frontend" -version = "0.70.0" +version = "0.73.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0153680ebce89aac7cad90a5442bb136faacfc86ea62587a01b8e8e79f8249c9" +checksum = "ae11da9ca99f987c29e3eb39ebe10e9b879ecca30f3aeaee13db5e8e02b80fb6" dependencies = [ "cranelift-codegen", "hashbrown", "log", "smallvec", - "target-lexicon", + "target-lexicon 0.12.0", ] [[package]] @@ -982,7 +982,7 @@ dependencies = [ "predicates", "regex", "rustc_version 0.3.3", - "target-lexicon", + "target-lexicon 0.11.2", "tempfile", ] @@ -1971,6 +1971,12 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "422045212ea98508ae3d28025bc5aaa2bd4a9cdaecd442a08da2ee620ee9ea95" +[[package]] +name = "target-lexicon" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ae3b39281e4b14b8123bdbaddd472b7dfe215e444181f2f9d2443c2444f834" + [[package]] name = "tempfile" version = "3.2.0" @@ -2010,7 +2016,7 @@ name = "test-generator" version = "0.1.0" dependencies = [ "anyhow", - "target-lexicon", + "target-lexicon 0.12.0", ] [[package]] @@ -2305,7 +2311,7 @@ dependencies = [ "libc", "loupe", "more-asserts", - "target-lexicon", + "target-lexicon 0.12.0", "tempfile", "thiserror", "wasmer-compiler", @@ -2411,7 +2417,7 @@ dependencies = [ "serde", "serde_bytes", "smallvec", - "target-lexicon", + "target-lexicon 0.12.0", "thiserror", "wasmer-types", "wasmer-vm", @@ -2432,7 +2438,7 @@ dependencies = [ "more-asserts", "rayon", "smallvec", - "target-lexicon", + "target-lexicon 0.12.0", "tracing", "wasmer-compiler", "wasmer-types", @@ -2456,7 +2462,7 @@ dependencies = [ "rustc_version 0.2.3", "semver 0.11.0", "smallvec", - "target-lexicon", + "target-lexicon 0.12.0", "wasmer-compiler", "wasmer-types", "wasmer-vm", @@ -2475,7 +2481,7 @@ dependencies = [ "more-asserts", "rayon", "smallvec", - "target-lexicon", + "target-lexicon 0.12.0", "wasmer-compiler", "wasmer-types", "wasmer-vm", @@ -2518,7 +2524,7 @@ dependencies = [ "rustc-demangle", "serde", "serde_bytes", - "target-lexicon", + "target-lexicon 0.12.0", "thiserror", "wasmer-compiler", "wasmer-types", diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index 080cdaf85a0..fcb94952ae4 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -94,18 +94,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cranelift-bforest" -version = "0.70.0" +version = "0.73.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f782ffb172d8095cbb4c6464d85432c3bcfa8609b0bb1dc27cfd35bd90e052" +checksum = "07f641ec9146b7d7498d78cd832007d66ca44a9b61f23474d1fb78e5a3701e99" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.70.0" +version = "0.73.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e0910022b490bd0a65d5baa1693b0475cdbeea1c26472343f2acea1f1f55b8" +checksum = "fd1f2c0cd4ac12c954116ab2e26e40df0d51db322a855b5664fa208bc32d6686" dependencies = [ "byteorder", "cranelift-bforest", @@ -122,9 +122,9 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.70.0" +version = "0.73.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cafe95cb5ac659e113549b2794a2c8d3a14f36e1a98728a6e0ea7a773be2129" +checksum = "105e11b2f0ff7ac81f80dd05ec938ce529a75e36f3d598360d806bb5bfa75e5a" dependencies = [ "cranelift-codegen-shared", "cranelift-entity", @@ -132,21 +132,21 @@ dependencies = [ [[package]] name = "cranelift-codegen-shared" -version = "0.70.0" +version = "0.73.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d1bd002e42cc094a131a8227d06d48df28ea3b9127e5e3bc3010e079858e9af" +checksum = "51e5eba2c1858d50abf023be4d88bd0450cb12d4ec2ba3ffac56353e6d09caf2" [[package]] name = "cranelift-entity" -version = "0.70.0" +version = "0.73.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e55e9043403f0dec775f317280015150e78b2352fb947d2f37407fd4ce6311c7" +checksum = "79fa6fdd77a8d317763cd21668d3e72b96e09ac8a974326c6149f7de5aafa8ed" [[package]] name = "cranelift-frontend" -version = "0.70.0" +version = "0.73.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0153680ebce89aac7cad90a5442bb136faacfc86ea62587a01b8e8e79f8249c9" +checksum = "ae11da9ca99f987c29e3eb39ebe10e9b879ecca30f3aeaee13db5e8e02b80fb6" dependencies = [ "cranelift-codegen", "log", @@ -969,9 +969,9 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.11.2" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "422045212ea98508ae3d28025bc5aaa2bd4a9cdaecd442a08da2ee620ee9ea95" +checksum = "64ae3b39281e4b14b8123bdbaddd472b7dfe215e444181f2f9d2443c2444f834" [[package]] name = "tempfile" diff --git a/lib/api/Cargo.toml b/lib/api/Cargo.toml index d1b5005d76c..2b5f17bf54c 100644 --- a/lib/api/Cargo.toml +++ b/lib/api/Cargo.toml @@ -26,7 +26,7 @@ cfg-if = "0.1" wat = { version = "1.0", optional = true } thiserror = "1.0" more-asserts = "0.2" -target-lexicon = { version = "0.11", default-features = false } +target-lexicon = { version = "0.12", default-features = false } loupe = "0.1" [target.'cfg(target_os = "windows")'.dependencies] @@ -66,11 +66,6 @@ cranelift = [ "wasmer-compiler-cranelift", "compiler", ] -# Enable Cranelift experimental x64 backend -cranelift-experimental-x64 = [ - "cranelift", - "wasmer-compiler-cranelift/experimental-x64", -] llvm = [ "wasmer-compiler-llvm", "compiler", diff --git a/lib/cli/Cargo.toml b/lib/cli/Cargo.toml index b0959de4a1e..0d65764a77c 100644 --- a/lib/cli/Cargo.toml +++ b/lib/cli/Cargo.toml @@ -103,11 +103,6 @@ cranelift = [ "wasmer-compiler-cranelift", "compiler", ] -# Enable Cranelift experimental x64 backend -cranelift-experimental-x64 = [ - "cranelift", - "wasmer-compiler-cranelift/experimental-x64", -] llvm = [ "wasmer-compiler-llvm", "compiler", diff --git a/lib/compiler-cranelift/Cargo.toml b/lib/compiler-cranelift/Cargo.toml index 6a2bca5a73d..41fc71a98da 100644 --- a/lib/compiler-cranelift/Cargo.toml +++ b/lib/compiler-cranelift/Cargo.toml @@ -15,9 +15,9 @@ edition = "2018" wasmer-compiler = { path = "../compiler", version = "1.0.2", features = ["translator"], default-features = false } wasmer-vm = { path = "../vm", version = "1.0.2" } wasmer-types = { path = "../types", version = "1.0.2", default-features = false, features = ["std"] } -cranelift-entity = { version = "0.70", default-features = false } -cranelift-codegen = { version = "0.70", default-features = false, features = ["x86", "arm64"] } -cranelift-frontend = { version = "0.70", default-features = false } +cranelift-entity = { version = "0.73", default-features = false } +cranelift-codegen = { version = "0.73", default-features = false, features = ["x86", "arm64"] } +cranelift-frontend = { version = "0.73", default-features = false } tracing = "0.1" hashbrown = { version = "0.9", optional = true } rayon = "1.5" @@ -27,8 +27,8 @@ smallvec = "1.6" loupe = "0.1" [dev-dependencies] -target-lexicon = { version = "0.11", default-features = false } -cranelift-codegen = { version = "0.70", features = ["all-arch"] } +target-lexicon = { version = "0.12", default-features = false } +cranelift-codegen = { version = "0.73", features = ["all-arch"] } lazy_static = "1.4" [badges] @@ -39,6 +39,3 @@ default = ["std", "unwind"] unwind = ["cranelift-codegen/unwind", "gimli"] std = ["cranelift-codegen/std", "cranelift-frontend/std", "wasmer-compiler/std", "wasmer-types/std"] core = ["hashbrown", "cranelift-codegen/core", "cranelift-frontend/core"] - -# Enable Cranelift experimental x64 backend -experimental-x64 = ["cranelift-codegen/x64"] diff --git a/lib/compiler-cranelift/src/translator/code_translator.rs b/lib/compiler-cranelift/src/translator/code_translator.rs index a2a09f0c66d..01738486535 100644 --- a/lib/compiler-cranelift/src/translator/code_translator.rs +++ b/lib/compiler-cranelift/src/translator/code_translator.rs @@ -25,6 +25,54 @@ //! //! That is why `translate_function_body` takes an object having the `WasmRuntime` trait as //! argument. +//! +//! There is extra complexity associated with translation of 128-bit SIMD instructions. +//! Wasm only considers there to be a single 128-bit vector type. But CLIF's type system +//! distinguishes different lane configurations, so considers 8X16, 16X8, 32X4 and 64X2 to be +//! different types. The result is that, in wasm, it's perfectly OK to take the output of (eg) +//! an `add.16x8` and use that as an operand of a `sub.32x4`, without using any cast. But when +//! translated into CLIF, that will cause a verifier error due to the apparent type mismatch. +//! +//! This file works around that problem by liberally inserting `bitcast` instructions in many +//! places -- mostly, before the use of vector values, either as arguments to CLIF instructions +//! or as block actual parameters. These are no-op casts which nevertheless have different +//! input and output types, and are used (mostly) to "convert" 16X8, 32X4 and 64X2-typed vectors +//! to the "canonical" type, 8X16. Hence the functions `optionally_bitcast_vector`, +//! `bitcast_arguments`, `pop*_with_bitcast`, `canonicalise_then_jump`, +//! `canonicalise_then_br{z,nz}`, `is_non_canonical_v128` and `canonicalise_v128_values`. +//! Note that the `bitcast*` functions are occasionally used to convert to some type other than +//! 8X16, but the `canonicalise*` functions always convert to type 8X16. +//! +//! Be careful when adding support for new vector instructions. And when adding new jumps, even +//! if they are apparently don't have any connection to vectors. Never generate any kind of +//! (inter-block) jump directly. Instead use `canonicalise_then_jump` and +//! `canonicalise_then_br{z,nz}`. +//! +//! The use of bitcasts is ugly and inefficient, but currently unavoidable: +//! +//! * they make the logic in this file fragile: miss out a bitcast for any reason, and there is +//! the risk of the system failing in the verifier. At least for debug builds. +//! +//! * in the new backends, they potentially interfere with pattern matching on CLIF -- the +//! patterns need to take into account the presence of bitcast nodes. +//! +//! * in the new backends, they get translated into machine-level vector-register-copy +//! instructions, none of which are actually necessary. We then depend on the register +//! allocator to coalesce them all out. +//! +//! * they increase the total number of CLIF nodes that have to be processed, hence slowing down +//! the compilation pipeline. Also, the extra coalescing work generates a slowdown. +//! +//! A better solution which would avoid all four problems would be to remove the 8X16, 16X8, +//! 32X4 and 64X2 types from CLIF and instead have a single V128 type. +//! +//! For further background see also: +//! +//! ("Too many raw_bitcasts in SIMD code") +//! +//! ("Add X128 type to represent WebAssembly's V128 type") +//! +//! ("Relax verification to allow I8X16 to act as a default vector type") use super::func_environ::{FuncEnvironment, GlobalVariable, ReturnMode}; use super::func_state::{ControlStackFrame, ElseData, FuncTranslationState, ValueExtraInfo}; @@ -531,7 +579,9 @@ pub fn translate_operator( Operator::Return => { let (return_count, br_destination) = { let frame = &mut state.control_stack[0]; - frame.set_branched_to_exit(); + if environ.return_mode() == ReturnMode::FallthroughReturn { + frame.set_branched_to_exit(); + } let return_count = frame.num_return_values(); (return_count, frame.br_destination()) }; @@ -554,6 +604,19 @@ pub fn translate_operator( state.popn(return_count); state.reachable = false; } + /********************************** Exception handing **********************************/ + Operator::Try { .. } + | Operator::Catch { .. } + | Operator::Throw { .. } + | Operator::Unwind + | Operator::Rethrow { .. } + | Operator::Delegate { .. } + | Operator::CatchAll => { + return Err(wasm_unsupported!( + "proposed exception handling operator {:?}", + op + )); + } /************************************ Calls **************************************** * The call instructions pop off their arguments from the stack and append their * return values to it. `call_indirect` needs environment support because there is an @@ -1081,6 +1144,7 @@ pub fn translate_operator( let (timeout, _) = state.pop1(); // 64 (fixed) let (expected, _) = state.pop1(); // 32 or 64 (per the `Ixx` in `IxxAtomicWait`) let (addr, _) = state.pop1(); // 32 (fixed) + let addr = fold_atomic_mem_addr(addr, memarg, implied_ty, builder); assert!(builder.func.dfg.value_type(expected) == implied_ty); // `fn translate_atomic_wait` can inspect the type of `expected` to figure out what // code it needs to generate, if it wants. @@ -1099,6 +1163,7 @@ pub fn translate_operator( let heap = state.get_heap(builder.func, memarg.memory, environ)?; let (count, _) = state.pop1(); // 32 (fixed) let (addr, _) = state.pop1(); // 32 (fixed) + let addr = fold_atomic_mem_addr(addr, memarg, I32, builder); let res = environ.translate_atomic_notify(builder.cursor(), heap_index, heap, addr, count)?; state.push1(res); @@ -1460,8 +1525,6 @@ pub fn translate_operator( | Operator::V128Load16Splat { memarg } | Operator::V128Load32Splat { memarg } | Operator::V128Load64Splat { memarg } => { - // TODO: remove this in favor of the single instruction LoadSplat code above - // which is not yet available in Cranelift 0.67 translate_load( memarg, ir::Opcode::Load, @@ -1472,18 +1535,42 @@ pub fn translate_operator( )?; let splatted = builder.ins().splat(type_of(op), state.pop1().0); state.push1(splatted) - - // let opcode = ir::Opcode::LoadSplat; - // let result_ty = type_of(op); - // let (flags, base, offset) = prepare_load( - // memarg, - // mem_op_size(opcode, result_ty.lane_type()), - // builder, - // state, - // environ, - // )?; - // let (load, dfg) = builder.ins().Load(opcode, result_ty, flags, offset, base); - // state.push1(dfg.first_result(load)) + } + Operator::V128Load32Zero { memarg } | Operator::V128Load64Zero { memarg } => { + translate_load( + memarg, + ir::Opcode::Load, + type_of(op).lane_type(), + builder, + state, + environ, + )?; + let as_vector = builder.ins().scalar_to_vector(type_of(op), state.pop1().0); + state.push1(as_vector) + } + Operator::V128Load8Lane { memarg, lane } + | Operator::V128Load16Lane { memarg, lane } + | Operator::V128Load32Lane { memarg, lane } + | Operator::V128Load64Lane { memarg, lane } => { + let vector = pop1_with_bitcast(state, type_of(op), builder); + translate_load( + memarg, + ir::Opcode::Load, + type_of(op).lane_type(), + builder, + state, + environ, + )?; + let replacement = state.pop1().0; + state.push1(builder.ins().insertlane(vector, replacement, *lane)) + } + Operator::V128Store8Lane { memarg, lane } + | Operator::V128Store16Lane { memarg, lane } + | Operator::V128Store32Lane { memarg, lane } + | Operator::V128Store64Lane { memarg, lane } => { + let vector = pop1_with_bitcast(state, type_of(op), builder); + state.push1(builder.ins().extractlane(vector, lane.clone())); + translate_store(memarg, ir::Opcode::Store, builder, state, environ)?; } Operator::I8x16ExtractLaneS { lane } | Operator::I16x8ExtractLaneS { lane } => { let vector = pop1_with_bitcast(state, type_of(op), builder); @@ -1527,8 +1614,8 @@ pub fn translate_operator( let shuffled = builder.ins().shuffle(a, b, mask); state.push1(shuffled) // At this point the original types of a and b are lost; users of this value (i.e. this - // Wasm-to-CLIF translator) may need to raw_bitcast for type-correctness. This is due - // to Wasm using the less specific v128 type for certain operations and more specific + // WASM-to-CLIF translator) may need to raw_bitcast for type-correctness. This is due + // to WASM using the less specific v128 type for certain operations and more specific // types (e.g. i8x16) for others. } Operator::I8x16Swizzle => { @@ -1583,7 +1670,7 @@ pub fn translate_operator( let a = pop1_with_bitcast(state, type_of(op), builder); state.push1(builder.ins().ineg(a)) } - Operator::I8x16Abs | Operator::I16x8Abs | Operator::I32x4Abs => { + Operator::I8x16Abs | Operator::I16x8Abs | Operator::I32x4Abs | Operator::I64x2Abs => { let a = pop1_with_bitcast(state, type_of(op), builder); state.push1(builder.ins().iabs(a)) } @@ -1652,26 +1739,31 @@ pub fn translate_operator( let bool_result = builder.ins().vany_true(a); state.push1(builder.ins().bint(I32, bool_result)) } - Operator::I8x16AllTrue | Operator::I16x8AllTrue | Operator::I32x4AllTrue => { + Operator::I8x16AllTrue + | Operator::I16x8AllTrue + | Operator::I32x4AllTrue + | Operator::I64x2AllTrue => { let a = pop1_with_bitcast(state, type_of(op), builder); let bool_result = builder.ins().vall_true(a); state.push1(builder.ins().bint(I32, bool_result)) } - Operator::I8x16Bitmask | Operator::I16x8Bitmask | Operator::I32x4Bitmask => { - unimplemented!("SIMD Operator {:?} not yet implemented", op); - // let a = pop1_with_bitcast(state, type_of(op), builder); - // state.push1(builder.ins().vhigh_bits(I32, a)); + Operator::I8x16Bitmask + | Operator::I16x8Bitmask + | Operator::I32x4Bitmask + | Operator::I64x2Bitmask => { + let a = pop1_with_bitcast(state, type_of(op), builder); + state.push1(builder.ins().vhigh_bits(I32, a)); } - Operator::I8x16Eq | Operator::I16x8Eq | Operator::I32x4Eq => { + Operator::I8x16Eq | Operator::I16x8Eq | Operator::I32x4Eq | Operator::I64x2Eq => { translate_vector_icmp(IntCC::Equal, type_of(op), builder, state) } - Operator::I8x16Ne | Operator::I16x8Ne | Operator::I32x4Ne => { + Operator::I8x16Ne | Operator::I16x8Ne | Operator::I32x4Ne | Operator::I64x2Ne => { translate_vector_icmp(IntCC::NotEqual, type_of(op), builder, state) } - Operator::I8x16GtS | Operator::I16x8GtS | Operator::I32x4GtS => { + Operator::I8x16GtS | Operator::I16x8GtS | Operator::I32x4GtS | Operator::I64x2GtS => { translate_vector_icmp(IntCC::SignedGreaterThan, type_of(op), builder, state) } - Operator::I8x16LtS | Operator::I16x8LtS | Operator::I32x4LtS => { + Operator::I8x16LtS | Operator::I16x8LtS | Operator::I32x4LtS | Operator::I64x2LtS => { translate_vector_icmp(IntCC::SignedLessThan, type_of(op), builder, state) } Operator::I8x16GtU | Operator::I16x8GtU | Operator::I32x4GtU => { @@ -1680,10 +1772,10 @@ pub fn translate_operator( Operator::I8x16LtU | Operator::I16x8LtU | Operator::I32x4LtU => { translate_vector_icmp(IntCC::UnsignedLessThan, type_of(op), builder, state) } - Operator::I8x16GeS | Operator::I16x8GeS | Operator::I32x4GeS => { + Operator::I8x16GeS | Operator::I16x8GeS | Operator::I32x4GeS | Operator::I64x2GeS => { translate_vector_icmp(IntCC::SignedGreaterThanOrEqual, type_of(op), builder, state) } - Operator::I8x16LeS | Operator::I16x8LeS | Operator::I32x4LeS => { + Operator::I8x16LeS | Operator::I16x8LeS | Operator::I32x4LeS | Operator::I64x2LeS => { translate_vector_icmp(IntCC::SignedLessThanOrEqual, type_of(op), builder, state) } Operator::I8x16GeU | Operator::I16x8GeU | Operator::I32x4GeU => translate_vector_icmp( @@ -1738,19 +1830,12 @@ pub fn translate_operator( state.push1(builder.ins().fmin(a, b)) } Operator::F32x4PMax | Operator::F64x2PMax => { - unimplemented!("SIMD Operator {:?} not yet implemented", op); - // let (a, b) = pop2_with_bitcast(state, type_of(op), builder); - // state.push1(builder.ins().fmax_pseudo(a, b)) + let (a, b) = pop2_with_bitcast(state, type_of(op), builder); + state.push1(builder.ins().fmax_pseudo(a, b)) } Operator::F32x4PMin | Operator::F64x2PMin => { - unimplemented!("SIMD Operator {:?} not yet implemented", op); - // let (a, b) = pop2_with_bitcast(state, type_of(op), builder); - // state.push1(builder.ins().fmin_pseudo(a, b)) - } - Operator::I32x4DotI16x8S - | Operator::V128Load32Zero { .. } - | Operator::V128Load64Zero { .. } => { - unimplemented!("SIMD Operator {:?} not yet implemented", op); + let (a, b) = pop2_with_bitcast(state, type_of(op), builder); + state.push1(builder.ins().fmin_pseudo(a, b)) } Operator::F32x4Sqrt | Operator::F64x2Sqrt => { let a = pop1_with_bitcast(state, type_of(op), builder); @@ -1772,6 +1857,10 @@ pub fn translate_operator( let a = pop1_with_bitcast(state, I32X4, builder); state.push1(builder.ins().fcvt_from_uint(F32X4, a)) } + Operator::F64x2ConvertLowI32x4S => { + let a = pop1_with_bitcast(state, I32X4, builder); + state.push1(builder.ins().fcvt_low_from_sint(F64X2, a)); + } Operator::I32x4TruncSatF32x4S => { let a = pop1_with_bitcast(state, F32X4, builder); state.push1(builder.ins().fcvt_to_sint_sat(I32X4, a)) @@ -1848,29 +1937,15 @@ pub fn translate_operator( let arg = pop1_with_bitcast(state, type_of(op), builder); state.push1(builder.ins().nearest(arg)); } - - Operator::ReturnCall { .. } | Operator::ReturnCallIndirect { .. } => { - return Err(wasm_unsupported!("proposed tail-call operator {:?}", op)); + Operator::I32x4DotI16x8S => { + let (a, b) = pop2_with_bitcast(state, I16X8, builder); + state.push1(builder.ins().widening_pairwise_dot_product_s(a, b)); } - - Operator::I64x2LtS - | Operator::I64x2GtS - | Operator::I64x2LeS - | Operator::I64x2GeS - | Operator::I8x16Popcnt - | Operator::I16x8ExtAddPairwiseI8x16S - | Operator::I16x8ExtAddPairwiseI8x16U - | Operator::I32x4ExtAddPairwiseI16x8S - | Operator::I32x4ExtAddPairwiseI16x8U - | Operator::I64x2Abs - | Operator::I64x2Eq - | Operator::I64x2Ne - | Operator::I64x2AllTrue - | Operator::I64x2Bitmask - | Operator::I64x2ExtendLowI32x4S + Operator::I64x2ExtendLowI32x4S | Operator::I64x2ExtendHighI32x4S | Operator::I64x2ExtendLowI32x4U | Operator::I64x2ExtendHighI32x4U + | Operator::I16x8Q15MulrSatS | Operator::I16x8ExtMulLowI8x16S | Operator::I16x8ExtMulHighI8x16S | Operator::I16x8ExtMulLowI8x16U @@ -1883,32 +1958,20 @@ pub fn translate_operator( | Operator::I64x2ExtMulHighI32x4S | Operator::I64x2ExtMulLowI32x4U | Operator::I64x2ExtMulHighI32x4U - | Operator::V128Load8Lane { .. } - | Operator::V128Load16Lane { .. } - | Operator::V128Load32Lane { .. } - | Operator::V128Load64Lane { .. } - | Operator::V128Store8Lane { .. } - | Operator::V128Store16Lane { .. } - | Operator::V128Store32Lane { .. } - | Operator::V128Store64Lane { .. } - | Operator::I16x8Q15MulrSatS + | Operator::I16x8ExtAddPairwiseI8x16S + | Operator::I16x8ExtAddPairwiseI8x16U + | Operator::I32x4ExtAddPairwiseI16x8S + | Operator::I32x4ExtAddPairwiseI16x8U | Operator::F32x4DemoteF64x2Zero | Operator::F64x2PromoteLowF32x4 - | Operator::F64x2ConvertLowI32x4S | Operator::F64x2ConvertLowI32x4U | Operator::I32x4TruncSatF64x2SZero - | Operator::I32x4TruncSatF64x2UZero => { - return Err(wasm_unsupported!("updated proposed simd operator {:?}", op)); + | Operator::I32x4TruncSatF64x2UZero + | Operator::I8x16Popcnt => { + return Err(wasm_unsupported!("proposed simd operator {:?}", op)); } - - Operator::Try { .. } - | Operator::Catch { .. } - | Operator::Throw { .. } - | Operator::Rethrow { .. } - | Operator::CatchAll - | Operator::Delegate { .. } - | Operator::Unwind => { - return Err(wasm_unsupported!("proposed exception operator {:?}", op)); + Operator::ReturnCall { .. } | Operator::ReturnCallIndirect { .. } => { + return Err(wasm_unsupported!("proposed tail-call operator {:?}", op)); } }; Ok(()) @@ -2152,7 +2215,9 @@ fn prepare_load( // Note that we don't set `is_aligned` here, even if the load instruction's // alignment immediate says it's aligned, because WebAssembly's immediate // field is just a hint, while Cranelift's aligned flag needs a guarantee. - let flags = MemFlags::new(); + // WebAssembly memory accesses are always little-endian. + let mut flags = MemFlags::new(); + flags.set_endianness(ir::Endianness::Little); Ok((flags, base, offset.into())) } @@ -2199,7 +2264,8 @@ fn translate_store( builder, ); // See the comments in `prepare_load` about the flags. - let flags = MemFlags::new(); + let mut flags = MemFlags::new(); + flags.set_endianness(ir::Endianness::Little); builder .ins() .Store(opcode, val_ty, flags, offset.into(), val, base); @@ -2211,7 +2277,7 @@ fn mem_op_size(opcode: ir::Opcode, ty: Type) -> u32 { ir::Opcode::Istore8 | ir::Opcode::Sload8 | ir::Opcode::Uload8 => 1, ir::Opcode::Istore16 | ir::Opcode::Sload16 | ir::Opcode::Uload16 => 2, ir::Opcode::Istore32 | ir::Opcode::Sload32 | ir::Opcode::Uload32 => 4, - ir::Opcode::Store | ir::Opcode::Load /* | ir::Opcode::LoadSplat */=> ty.bytes(), + ir::Opcode::Store | ir::Opcode::Load => ty.bytes(), _ => panic!("unknown size of mem op for {:?}", opcode), } } @@ -2222,6 +2288,42 @@ fn translate_icmp(cc: IntCC, builder: &mut FunctionBuilder, state: &mut FuncTran state.push1(builder.ins().bint(I32, val)); } +fn fold_atomic_mem_addr( + linear_mem_addr: Value, + memarg: &MemoryImmediate, + access_ty: Type, + builder: &mut FunctionBuilder, +) -> Value { + let access_ty_bytes = access_ty.bytes(); + let final_lma = if memarg.offset > 0 { + assert!(builder.func.dfg.value_type(linear_mem_addr) == I32); + let linear_mem_addr = builder.ins().uextend(I64, linear_mem_addr); + let a = builder + .ins() + .iadd_imm(linear_mem_addr, i64::from(memarg.offset)); + let cflags = builder.ins().ifcmp_imm(a, 0x1_0000_0000i64); + builder.ins().trapif( + IntCC::UnsignedGreaterThanOrEqual, + cflags, + ir::TrapCode::HeapOutOfBounds, + ); + builder.ins().ireduce(I32, a) + } else { + linear_mem_addr + }; + assert!(access_ty_bytes == 4 || access_ty_bytes == 8); + let final_lma_misalignment = builder + .ins() + .band_imm(final_lma, i64::from(access_ty_bytes - 1)); + let f = builder + .ins() + .ifcmp_imm(final_lma_misalignment, i64::from(0)); + builder + .ins() + .trapif(IntCC::NotEqual, f, ir::TrapCode::HeapMisaligned); + final_lma +} + // For an atomic memory operation, emit an alignment check for the linear memory address, // and then compute the final effective address. fn finalise_atomic_mem_addr( @@ -2303,7 +2405,8 @@ fn translate_atomic_rmw( finalise_atomic_mem_addr(linear_mem_addr, memarg, access_ty, builder, state, environ)?; // See the comments in `prepare_load` about the flags. - let flags = MemFlags::new(); + let mut flags = MemFlags::new(); + flags.set_endianness(ir::Endianness::Little); let mut res = builder .ins() .atomic_rmw(access_ty, flags, op, final_effective_address, arg2); @@ -2356,7 +2459,8 @@ fn translate_atomic_cas( finalise_atomic_mem_addr(linear_mem_addr, memarg, access_ty, builder, state, environ)?; // See the comments in `prepare_load` about the flags. - let flags = MemFlags::new(); + let mut flags = MemFlags::new(); + flags.set_endianness(ir::Endianness::Little); let mut res = builder .ins() .atomic_cas(flags, final_effective_address, expected, replacement); @@ -2398,7 +2502,8 @@ fn translate_atomic_load( finalise_atomic_mem_addr(linear_mem_addr, memarg, access_ty, builder, state, environ)?; // See the comments in `prepare_load` about the flags. - let flags = MemFlags::new(); + let mut flags = MemFlags::new(); + flags.set_endianness(ir::Endianness::Little); let mut res = builder .ins() .atomic_load(access_ty, flags, final_effective_address); @@ -2444,7 +2549,8 @@ fn translate_atomic_store( finalise_atomic_mem_addr(linear_mem_addr, memarg, access_ty, builder, state, environ)?; // See the comments in `prepare_load` about the flags. - let flags = MemFlags::new(); + let mut flags = MemFlags::new(); + flags.set_endianness(ir::Endianness::Little); builder .ins() .atomic_store(flags, data, final_effective_address); @@ -2529,11 +2635,14 @@ fn type_of(operator: &Operator) -> Type { | Operator::V128AndNot | Operator::V128Or | Operator::V128Xor + | Operator::V128AnyTrue | Operator::V128Bitselect => I8X16, // default type representing V128 Operator::I8x16Shuffle { .. } | Operator::I8x16Splat | Operator::V128Load8Splat { .. } + | Operator::V128Load8Lane { .. } + | Operator::V128Store8Lane { .. } | Operator::I8x16ExtractLaneS { .. } | Operator::I8x16ExtractLaneU { .. } | Operator::I8x16ReplaceLane { .. } @@ -2568,6 +2677,8 @@ fn type_of(operator: &Operator) -> Type { Operator::I16x8Splat | Operator::V128Load16Splat { .. } + | Operator::V128Load16Lane { .. } + | Operator::V128Store16Lane { .. } | Operator::I16x8ExtractLaneS { .. } | Operator::I16x8ExtractLaneU { .. } | Operator::I16x8ReplaceLane { .. } @@ -2603,6 +2714,8 @@ fn type_of(operator: &Operator) -> Type { Operator::I32x4Splat | Operator::V128Load32Splat { .. } + | Operator::V128Load32Lane { .. } + | Operator::V128Store32Lane { .. } | Operator::I32x4ExtractLane { .. } | Operator::I32x4ReplaceLane { .. } | Operator::I32x4Eq @@ -2630,19 +2743,32 @@ fn type_of(operator: &Operator) -> Type { | Operator::I32x4MaxU | Operator::F32x4ConvertI32x4S | Operator::F32x4ConvertI32x4U - | Operator::I32x4Bitmask => I32X4, + | Operator::I32x4Bitmask + | Operator::V128Load32Zero { .. } => I32X4, Operator::I64x2Splat | Operator::V128Load64Splat { .. } + | Operator::V128Load64Lane { .. } + | Operator::V128Store64Lane { .. } | Operator::I64x2ExtractLane { .. } | Operator::I64x2ReplaceLane { .. } + | Operator::I64x2Eq + | Operator::I64x2Ne + | Operator::I64x2LtS + | Operator::I64x2GtS + | Operator::I64x2LeS + | Operator::I64x2GeS | Operator::I64x2Neg + | Operator::I64x2Abs + | Operator::I64x2AllTrue | Operator::I64x2Shl | Operator::I64x2ShrS | Operator::I64x2ShrU | Operator::I64x2Add | Operator::I64x2Sub - | Operator::I64x2Mul => I64X2, + | Operator::I64x2Mul + | Operator::I64x2Bitmask + | Operator::V128Load64Zero { .. } => I64X2, Operator::F32x4Splat | Operator::F32x4ExtractLane { .. } @@ -2720,10 +2846,10 @@ fn optionally_bitcast_vector( #[inline(always)] fn is_non_canonical_v128(ty: ir::Type) -> bool { - matches!( - ty, - B8X16 | B16X8 | B32X4 | B64X2 | I64X2 | I32X4 | I16X8 | F32X4 | F64X2 - ) + match ty { + B8X16 | B16X8 | B32X4 | B64X2 | I64X2 | I32X4 | I16X8 | F32X4 | F64X2 => true, + _ => false, + } } /// Cast to I8X16, any vector values in `values` that are of "non-canonical" type (meaning, not diff --git a/lib/compiler-cranelift/src/translator/translation_utils.rs b/lib/compiler-cranelift/src/translator/translation_utils.rs index 69d40937520..81e940ac18c 100644 --- a/lib/compiler-cranelift/src/translator/translation_utils.rs +++ b/lib/compiler-cranelift/src/translator/translation_utils.rs @@ -89,6 +89,7 @@ pub fn irreloc_to_relocationkind(reloc: Reloc) -> RelocationKind { Reloc::X86PCRelRodata4 => RelocationKind::X86PCRelRodata4, Reloc::X86CallPCRel4 => RelocationKind::X86CallPCRel4, Reloc::X86CallPLTRel4 => RelocationKind::X86CallPLTRel4, + Reloc::X86GOTPCRel4 => RelocationKind::X86GOTPCRel4, _ => panic!("The relocation {} is not yet supported.", reloc), } } diff --git a/lib/compiler-llvm/Cargo.toml b/lib/compiler-llvm/Cargo.toml index cd5465f7a03..e343a7522a7 100644 --- a/lib/compiler-llvm/Cargo.toml +++ b/lib/compiler-llvm/Cargo.toml @@ -15,7 +15,7 @@ edition = "2018" wasmer-compiler = { path = "../compiler", version = "1.0.2", features = ["translator"] } wasmer-vm = { path = "../vm", version = "1.0.2" } wasmer-types = { path = "../types", version = "1.0.2" } -target-lexicon = { version = "0.11", default-features = false } +target-lexicon = { version = "0.12", default-features = false } smallvec = "1.6" object = { version = "0.23", default-features = false, features = ["read"] } libc = { version = "^0.2", default-features = false } diff --git a/lib/compiler-singlepass/Cargo.toml b/lib/compiler-singlepass/Cargo.toml index abdb61845d3..0def257eb59 100644 --- a/lib/compiler-singlepass/Cargo.toml +++ b/lib/compiler-singlepass/Cargo.toml @@ -26,7 +26,7 @@ smallvec = "1.6" loupe = "0.1" [dev-dependencies] -target-lexicon = { version = "0.11", default-features = false } +target-lexicon = { version = "0.12", default-features = false } [badges] maintenance = { status = "actively-developed" } diff --git a/lib/compiler/Cargo.toml b/lib/compiler/Cargo.toml index 0e1c8c01c19..8ebc198374a 100644 --- a/lib/compiler/Cargo.toml +++ b/lib/compiler/Cargo.toml @@ -14,7 +14,7 @@ edition = "2018" wasmer-vm = { path = "../vm", version = "1.0.2" } wasmer-types = { path = "../types", version = "1.0.2", default-features = false } wasmparser = { version = "0.78", optional = true, default-features = false } -target-lexicon = { version = "0.11", default-features = false } +target-lexicon = { version = "0.12", default-features = false } enumset = "1.0" hashbrown = { version = "0.9", optional = true } serde = { version = "1.0", features = ["derive"], optional = true } diff --git a/lib/compiler/src/relocation.rs b/lib/compiler/src/relocation.rs index 1a02c9198a0..ab71705104d 100644 --- a/lib/compiler/src/relocation.rs +++ b/lib/compiler/src/relocation.rs @@ -44,9 +44,8 @@ pub enum RelocationKind { X86CallPCRel4, /// x86 call to PLT-relative 4-byte X86CallPLTRel4, - // /// x86 GOT PC-relative 4-byte - // X86GOTPCRel4, - + /// x86 GOT PC-relative 4-byte + X86GOTPCRel4, // /// Arm32 call target // Arm32Call, @@ -75,7 +74,7 @@ impl fmt::Display for RelocationKind { Self::X86PCRelRodata4 => write!(f, "PCRelRodata4"), Self::X86CallPCRel4 => write!(f, "CallPCRel4"), Self::X86CallPLTRel4 => write!(f, "CallPLTRel4"), - // Self::X86GOTPCRel4 => write!(f, "GOTPCRel4"), + Self::X86GOTPCRel4 => write!(f, "GOTPCRel4"), // Self::Arm32Call | Self::Arm64Call | Self::RiscvCall => write!(f, "Call"), // Self::ElfX86_64TlsGd => write!(f, "ElfX86_64TlsGd"), diff --git a/lib/deprecated/runtime-core/Cargo.lock b/lib/deprecated/runtime-core/Cargo.lock index c840e25d562..386fa05030e 100644 --- a/lib/deprecated/runtime-core/Cargo.lock +++ b/lib/deprecated/runtime-core/Cargo.lock @@ -124,18 +124,18 @@ checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" [[package]] name = "cranelift-bforest" -version = "0.70.0" +version = "0.73.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f782ffb172d8095cbb4c6464d85432c3bcfa8609b0bb1dc27cfd35bd90e052" +checksum = "07f641ec9146b7d7498d78cd832007d66ca44a9b61f23474d1fb78e5a3701e99" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.70.0" +version = "0.73.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e0910022b490bd0a65d5baa1693b0475cdbeea1c26472343f2acea1f1f55b8" +checksum = "fd1f2c0cd4ac12c954116ab2e26e40df0d51db322a855b5664fa208bc32d6686" dependencies = [ "byteorder", "cranelift-bforest", @@ -152,9 +152,9 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.70.0" +version = "0.73.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cafe95cb5ac659e113549b2794a2c8d3a14f36e1a98728a6e0ea7a773be2129" +checksum = "105e11b2f0ff7ac81f80dd05ec938ce529a75e36f3d598360d806bb5bfa75e5a" dependencies = [ "cranelift-codegen-shared", "cranelift-entity", @@ -162,24 +162,21 @@ dependencies = [ [[package]] name = "cranelift-codegen-shared" -version = "0.70.0" +version = "0.73.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d1bd002e42cc094a131a8227d06d48df28ea3b9127e5e3bc3010e079858e9af" +checksum = "51e5eba2c1858d50abf023be4d88bd0450cb12d4ec2ba3ffac56353e6d09caf2" [[package]] name = "cranelift-entity" -version = "0.70.0" +version = "0.73.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e55e9043403f0dec775f317280015150e78b2352fb947d2f37407fd4ce6311c7" -dependencies = [ - "serde", -] +checksum = "79fa6fdd77a8d317763cd21668d3e72b96e09ac8a974326c6149f7de5aafa8ed" [[package]] name = "cranelift-frontend" -version = "0.70.0" +version = "0.73.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0153680ebce89aac7cad90a5442bb136faacfc86ea62587a01b8e8e79f8249c9" +checksum = "ae11da9ca99f987c29e3eb39ebe10e9b879ecca30f3aeaee13db5e8e02b80fb6" dependencies = [ "cranelift-codegen", "log", @@ -1061,9 +1058,9 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.11.1" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ee5a98e506fb7231a304c3a1bd7c132a55016cf65001e0282480665870dfcb9" +checksum = "64ae3b39281e4b14b8123bdbaddd472b7dfe215e444181f2f9d2443c2444f834" [[package]] name = "tempfile" @@ -1231,7 +1228,6 @@ dependencies = [ "loupe", "more-asserts", "rayon", - "serde", "smallvec", "tracing", "wasmer-compiler", @@ -1273,7 +1269,6 @@ dependencies = [ "loupe", "more-asserts", "rayon", - "serde", "smallvec", "wasmer-compiler", "wasmer-types", diff --git a/lib/engine/Cargo.toml b/lib/engine/Cargo.toml index 83d80f9c70d..8ef7d2a1e53 100644 --- a/lib/engine/Cargo.toml +++ b/lib/engine/Cargo.toml @@ -14,7 +14,7 @@ edition = "2018" wasmer-types = { path = "../types", version = "1.0.2" } wasmer-compiler = { path = "../compiler", version = "1.0.2" } wasmer-vm = { path = "../vm", version = "1.0.2" } -target-lexicon = { version = "0.11", default-features = false } +target-lexicon = { version = "0.12", default-features = false } # flexbuffers = { path = "../../../flatbuffers/rust/flexbuffers", version = "0.1.0" } backtrace = "0.3" rustc-demangle = "0.1" diff --git a/lib/object/src/module.rs b/lib/object/src/module.rs index b824403e3d3..8aba8b72b21 100644 --- a/lib/object/src/module.rs +++ b/lib/object/src/module.rs @@ -209,11 +209,7 @@ pub fn emit_compilation( // Add relocations (function and sections) let (relocation_size, relocation_kind, relocation_encoding) = match triple.architecture { - Architecture::X86_64 => ( - 32, - RelocationKind::PltRelative, - RelocationEncoding::X86Branch, - ), + Architecture::X86_64 => (32, RelocationKind::GotRelative, RelocationEncoding::Generic), // Object doesn't fully support it yet // Architecture::Aarch64(_) => ( // 32, diff --git a/tests/ignores.txt b/tests/ignores.txt index a7af5f2afa5..4acbf38eb7e 100644 --- a/tests/ignores.txt +++ b/tests/ignores.txt @@ -12,6 +12,7 @@ llvm::spec::skip_stack_guard_page on darwin # TODO(https://github.com/wasmerio/wasmer/issues/1727): Traps in native engine cranelift::spec::linking on native +cranelift::spec::bulk on native # https://github.com/wasmerio/wasmer/issues/1722 llvm::spec::skip_stack_guard_page on native @@ -35,9 +36,6 @@ cranelift::spec::skip_stack_guard_page on aarch64 # due to breaking changes in the SIMD proposal, we have to disable these spec tests # note we've not pulled in the updated spec tests yet, so expect more breakage -cranelift::spec::simd::simd_boolean -cranelift::spec::simd::simd_lane - # Frontends ## WASI @@ -92,23 +90,14 @@ wasitests::snapshot1::unix_open_special_files on windows # Updated spectests -# bulk memory -cranelift::spec::bulk on native # new simd cranelift::spec::simd::simd_conversions -cranelift::spec::simd::simd_f32x4_pmin_pmax -cranelift::spec::simd::simd_f32x4_rounding -cranelift::spec::simd::simd_f64x2_pmin_pmax -cranelift::spec::simd::simd_f64x2_rounding cranelift::spec::simd::simd_i16x8_extadd_pairwise_i8x16 cranelift::spec::simd::simd_i16x8_extmul_i8x16 cranelift::spec::simd::simd_i16x8_q15mulr_sat_s -cranelift::spec::simd::simd_i32x4_dot_i16x8 cranelift::spec::simd::simd_i32x4_extadd_pairwise_i16x8 cranelift::spec::simd::simd_i32x4_extmul_i16x8 cranelift::spec::simd::simd_i32x4_trunc_sat_f64x2 -cranelift::spec::simd::simd_i64x2_arith2 -cranelift::spec::simd::simd_i64x2_cmp cranelift::spec::simd::simd_i64x2_extmul_i32x4 cranelift::spec::simd::simd_i8x16_arith2 cranelift::spec::simd::simd_int_to_int_extend diff --git a/tests/lib/test-generator/Cargo.toml b/tests/lib/test-generator/Cargo.toml index cbccbf782d3..f2425545d7e 100644 --- a/tests/lib/test-generator/Cargo.toml +++ b/tests/lib/test-generator/Cargo.toml @@ -7,7 +7,7 @@ license = "Apache-2.0 WITH LLVM-exception" [dependencies] anyhow = "1.0" -target-lexicon = "0.11" +target-lexicon = "0.12" [features] test-native = []