diff --git a/CHANGELOG.md b/CHANGELOG.md index a11365bb9..49d90aaae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ Blocks of changes will separated by version increments. ## **[Unreleased]** +- [#863](https://github.com/wasmerio/wasmer/pull/863) Fix min and max for cases involving NaN and negative zero when using the LLVM backend. + ## 0.8.0 - 2019-10-02 Special thanks to @jdanford for their contributions! diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 8ac76fe26..9ccb0c990 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -935,7 +935,8 @@ impl FunctionCodeGenerator for LLVMFunctionCodeGenerator { let signal_mem = ctx.signal_mem(); let iv = builder .build_store(signal_mem, context.i8_type().const_int(0 as u64, false)); - iv.set_volatile(true); + // Any 'store' can be made volatile. + iv.set_volatile(true).unwrap(); finalize_opcode_stack_map( intrinsics, builder, @@ -2420,14 +2421,11 @@ impl FunctionCodeGenerator for LLVMFunctionCodeGenerator { } Operator::I32Clz => { let input = state.pop1()?; - let ensure_defined_zero = intrinsics - .i1_ty - .const_int(1 as u64, false) - .as_basic_value_enum(); + let is_zero_undef = intrinsics.i1_zero.as_basic_value_enum(); let res = builder .build_call( intrinsics.ctlz_i32, - &[input, ensure_defined_zero], + &[input, is_zero_undef], &state.var_name(), ) .try_as_basic_value() @@ -2437,14 +2435,11 @@ impl FunctionCodeGenerator for LLVMFunctionCodeGenerator { } Operator::I64Clz => { let input = state.pop1()?; - let ensure_defined_zero = intrinsics - .i1_ty - .const_int(1 as u64, false) - .as_basic_value_enum(); + let is_zero_undef = intrinsics.i1_zero.as_basic_value_enum(); let res = builder .build_call( intrinsics.ctlz_i64, - &[input, ensure_defined_zero], + &[input, is_zero_undef], &state.var_name(), ) .try_as_basic_value() @@ -2454,14 +2449,11 @@ impl FunctionCodeGenerator for LLVMFunctionCodeGenerator { } Operator::I32Ctz => { let input = state.pop1()?; - let ensure_defined_zero = intrinsics - .i1_ty - .const_int(1 as u64, false) - .as_basic_value_enum(); + let is_zero_undef = intrinsics.i1_zero.as_basic_value_enum(); let res = builder .build_call( intrinsics.cttz_i32, - &[input, ensure_defined_zero], + &[input, is_zero_undef], &state.var_name(), ) .try_as_basic_value() @@ -2471,14 +2463,11 @@ impl FunctionCodeGenerator for LLVMFunctionCodeGenerator { } Operator::I64Ctz => { let input = state.pop1()?; - let ensure_defined_zero = intrinsics - .i1_ty - .const_int(1 as u64, false) - .as_basic_value_enum(); + let is_zero_undef = intrinsics.i1_zero.as_basic_value_enum(); let res = builder .build_call( intrinsics.cttz_i64, - &[input, ensure_defined_zero], + &[input, is_zero_undef], &state.var_name(), ) .try_as_basic_value() @@ -2692,86 +2681,404 @@ impl FunctionCodeGenerator for LLVMFunctionCodeGenerator { state.push1(bits); } Operator::F32Min => { + // This implements the same logic as LLVM's @llvm.minimum + // intrinsic would, but x86 lowering of that intrinsics + // encounters a fatal error in LLVM 8 and LLVM 9. let (v1, v2) = state.pop2()?; - let res = builder - .build_call(intrinsics.minimum_f32, &[v1, v2], &state.var_name()) - .try_as_basic_value() - .left() - .unwrap(); + let v1 = canonicalize_nans(builder, intrinsics, v1); + let v2 = canonicalize_nans(builder, intrinsics, v2); + let (v1, v2) = (v1.into_float_value(), v2.into_float_value()); + let v1_is_nan = builder.build_float_compare( + FloatPredicate::UNO, + v1, + intrinsics.f32_zero, + "nan", + ); + let v2_is_not_nan = builder.build_float_compare( + FloatPredicate::ORD, + v2, + intrinsics.f32_zero, + "notnan", + ); + let v1_repr = builder + .build_bitcast(v1, intrinsics.i32_ty, "") + .into_int_value(); + let v2_repr = builder + .build_bitcast(v2, intrinsics.i32_ty, "") + .into_int_value(); + let repr_ne = builder.build_int_compare(IntPredicate::NE, v1_repr, v2_repr, ""); + let float_eq = builder.build_float_compare(FloatPredicate::OEQ, v1, v2, ""); + let min_cmp = builder.build_float_compare(FloatPredicate::OLT, v1, v2, ""); + let negative_zero = intrinsics.f32_ty.const_float(-0.0); + let v2 = builder + .build_select( + builder.build_and( + builder.build_and(float_eq, repr_ne, ""), + v2_is_not_nan, + "", + ), + negative_zero, + v2, + "", + ) + .into_float_value(); + let res = + builder.build_select(builder.build_or(v1_is_nan, min_cmp, ""), v1, v2, ""); state.push1(res); } Operator::F64Min => { + // This implements the same logic as LLVM's @llvm.minimum + // intrinsic would, but x86 lowering of that intrinsics + // encounters a fatal error in LLVM 8 and LLVM 9. let (v1, v2) = state.pop2()?; - let res = builder - .build_call(intrinsics.minimum_f64, &[v1, v2], &state.var_name()) - .try_as_basic_value() - .left() - .unwrap(); + let v1 = canonicalize_nans(builder, intrinsics, v1); + let v2 = canonicalize_nans(builder, intrinsics, v2); + let (v1, v2) = (v1.into_float_value(), v2.into_float_value()); + let v1_is_nan = builder.build_float_compare( + FloatPredicate::UNO, + v1, + intrinsics.f64_zero, + "nan", + ); + let v2_is_not_nan = builder.build_float_compare( + FloatPredicate::ORD, + v2, + intrinsics.f64_zero, + "notnan", + ); + let v1_repr = builder + .build_bitcast(v1, intrinsics.i64_ty, "") + .into_int_value(); + let v2_repr = builder + .build_bitcast(v2, intrinsics.i64_ty, "") + .into_int_value(); + let repr_ne = builder.build_int_compare(IntPredicate::NE, v1_repr, v2_repr, ""); + let float_eq = builder.build_float_compare(FloatPredicate::OEQ, v1, v2, ""); + let min_cmp = builder.build_float_compare(FloatPredicate::OLT, v1, v2, ""); + let negative_zero = intrinsics.f64_ty.const_float(-0.0); + let v2 = builder + .build_select( + builder.build_and( + builder.build_and(float_eq, repr_ne, ""), + v2_is_not_nan, + "", + ), + negative_zero, + v2, + "", + ) + .into_float_value(); + let res = + builder.build_select(builder.build_or(v1_is_nan, min_cmp, ""), v1, v2, ""); state.push1(res); } Operator::F32x4Min => { + // This implements the same logic as LLVM's @llvm.minimum + // intrinsic would, but x86 lowering of that intrinsics + // encounters a fatal error in LLVM 8 and LLVM 9. let (v1, v2) = state.pop2()?; let v1 = builder.build_bitcast(v1, intrinsics.f32x4_ty, ""); let v2 = builder.build_bitcast(v2, intrinsics.f32x4_ty, ""); - let res = builder - .build_call(intrinsics.minimum_f32x4, &[v1, v2], &state.var_name()) - .try_as_basic_value() - .left() - .unwrap(); + let v1 = canonicalize_nans(builder, intrinsics, v1); + let v2 = canonicalize_nans(builder, intrinsics, v2); + let (v1, v2) = (v1.into_vector_value(), v2.into_vector_value()); + let v1_is_nan = builder.build_float_compare( + FloatPredicate::UNO, + v1, + intrinsics.f32x4_zero, + "nan", + ); + let v2_is_not_nan = builder.build_float_compare( + FloatPredicate::ORD, + v2, + intrinsics.f32x4_zero, + "notnan", + ); + let v1_repr = builder + .build_bitcast(v1, intrinsics.i32x4_ty, "") + .into_vector_value(); + let v2_repr = builder + .build_bitcast(v2, intrinsics.i32x4_ty, "") + .into_vector_value(); + let repr_ne = builder.build_int_compare(IntPredicate::NE, v1_repr, v2_repr, ""); + let float_eq = builder.build_float_compare(FloatPredicate::OEQ, v1, v2, ""); + let min_cmp = builder.build_float_compare(FloatPredicate::OLT, v1, v2, ""); + let negative_zero = splat_vector( + builder, + intrinsics, + intrinsics.f32_ty.const_float(-0.0).as_basic_value_enum(), + intrinsics.f32x4_ty, + "", + ); + let v2 = builder + .build_select( + builder.build_and( + builder.build_and(float_eq, repr_ne, ""), + v2_is_not_nan, + "", + ), + negative_zero, + v2, + "", + ) + .into_vector_value(); + let res = + builder.build_select(builder.build_or(v1_is_nan, min_cmp, ""), v1, v2, ""); let res = builder.build_bitcast(res, intrinsics.i128_ty, ""); state.push1(res); } Operator::F64x2Min => { + // This implements the same logic as LLVM's @llvm.minimum + // intrinsic would, but x86 lowering of that intrinsics + // encounters a fatal error in LLVM 8 and LLVM 9. let (v1, v2) = state.pop2()?; let v1 = builder.build_bitcast(v1, intrinsics.f64x2_ty, ""); let v2 = builder.build_bitcast(v2, intrinsics.f64x2_ty, ""); - let res = builder - .build_call(intrinsics.minimum_f64x2, &[v1, v2], &state.var_name()) - .try_as_basic_value() - .left() - .unwrap(); + let v1 = canonicalize_nans(builder, intrinsics, v1); + let v2 = canonicalize_nans(builder, intrinsics, v2); + let (v1, v2) = (v1.into_vector_value(), v2.into_vector_value()); + let v1_is_nan = builder.build_float_compare( + FloatPredicate::UNO, + v1, + intrinsics.f64x2_zero, + "nan", + ); + let v2_is_not_nan = builder.build_float_compare( + FloatPredicate::ORD, + v2, + intrinsics.f64x2_zero, + "notnan", + ); + let v1_repr = builder + .build_bitcast(v1, intrinsics.i64x2_ty, "") + .into_vector_value(); + let v2_repr = builder + .build_bitcast(v2, intrinsics.i64x2_ty, "") + .into_vector_value(); + let repr_ne = builder.build_int_compare(IntPredicate::NE, v1_repr, v2_repr, ""); + let float_eq = builder.build_float_compare(FloatPredicate::OEQ, v1, v2, ""); + let min_cmp = builder.build_float_compare(FloatPredicate::OLT, v1, v2, ""); + let negative_zero = splat_vector( + builder, + intrinsics, + intrinsics.f64_ty.const_float(-0.0).as_basic_value_enum(), + intrinsics.f64x2_ty, + "", + ); + let v2 = builder + .build_select( + builder.build_and( + builder.build_and(float_eq, repr_ne, ""), + v2_is_not_nan, + "", + ), + negative_zero, + v2, + "", + ) + .into_vector_value(); + let res = + builder.build_select(builder.build_or(v1_is_nan, min_cmp, ""), v1, v2, ""); let res = builder.build_bitcast(res, intrinsics.i128_ty, ""); state.push1(res); } Operator::F32Max => { + // This implements the same logic as LLVM's @llvm.maximum + // intrinsic would, but x86 lowering of that intrinsics + // encounters a fatal error in LLVM 8 and LLVM 9. let (v1, v2) = state.pop2()?; - let res = builder - .build_call(intrinsics.maximum_f32, &[v1, v2], &state.var_name()) - .try_as_basic_value() - .left() - .unwrap(); + let v1 = canonicalize_nans(builder, intrinsics, v1); + let v2 = canonicalize_nans(builder, intrinsics, v2); + let (v1, v2) = (v1.into_float_value(), v2.into_float_value()); + let v1_is_nan = builder.build_float_compare( + FloatPredicate::UNO, + v1, + intrinsics.f32_zero, + "nan", + ); + let v2_is_not_nan = builder.build_float_compare( + FloatPredicate::ORD, + v2, + intrinsics.f32_zero, + "notnan", + ); + let v1_repr = builder + .build_bitcast(v1, intrinsics.i32_ty, "") + .into_int_value(); + let v2_repr = builder + .build_bitcast(v2, intrinsics.i32_ty, "") + .into_int_value(); + let repr_ne = builder.build_int_compare(IntPredicate::NE, v1_repr, v2_repr, ""); + let float_eq = builder.build_float_compare(FloatPredicate::OEQ, v1, v2, ""); + let min_cmp = builder.build_float_compare(FloatPredicate::OGT, v1, v2, ""); + let v2 = builder + .build_select( + builder.build_and( + builder.build_and(float_eq, repr_ne, ""), + v2_is_not_nan, + "", + ), + intrinsics.f32_zero, + v2, + "", + ) + .into_float_value(); + let res = + builder.build_select(builder.build_or(v1_is_nan, min_cmp, ""), v1, v2, ""); state.push1(res); } Operator::F64Max => { + // This implements the same logic as LLVM's @llvm.maximum + // intrinsic would, but x86 lowering of that intrinsics + // encounters a fatal error in LLVM 8 and LLVM 9. let (v1, v2) = state.pop2()?; - let res = builder - .build_call(intrinsics.maximum_f64, &[v1, v2], &state.var_name()) - .try_as_basic_value() - .left() - .unwrap(); + let v1 = canonicalize_nans(builder, intrinsics, v1); + let v2 = canonicalize_nans(builder, intrinsics, v2); + let (v1, v2) = (v1.into_float_value(), v2.into_float_value()); + let v1_is_nan = builder.build_float_compare( + FloatPredicate::UNO, + v1, + intrinsics.f64_zero, + "nan", + ); + let v2_is_not_nan = builder.build_float_compare( + FloatPredicate::ORD, + v2, + intrinsics.f64_zero, + "notnan", + ); + let v1_repr = builder + .build_bitcast(v1, intrinsics.i64_ty, "") + .into_int_value(); + let v2_repr = builder + .build_bitcast(v2, intrinsics.i64_ty, "") + .into_int_value(); + let repr_ne = builder.build_int_compare(IntPredicate::NE, v1_repr, v2_repr, ""); + let float_eq = builder.build_float_compare(FloatPredicate::OEQ, v1, v2, ""); + let min_cmp = builder.build_float_compare(FloatPredicate::OGT, v1, v2, ""); + let v2 = builder + .build_select( + builder.build_and( + builder.build_and(float_eq, repr_ne, ""), + v2_is_not_nan, + "", + ), + intrinsics.f64_zero, + v2, + "", + ) + .into_float_value(); + let res = + builder.build_select(builder.build_or(v1_is_nan, min_cmp, ""), v1, v2, ""); state.push1(res); } Operator::F32x4Max => { + // This implements the same logic as LLVM's @llvm.maximum + // intrinsic would, but x86 lowering of that intrinsics + // encounters a fatal error in LLVM 8 and LLVM 9. let (v1, v2) = state.pop2()?; let v1 = builder.build_bitcast(v1, intrinsics.f32x4_ty, ""); let v2 = builder.build_bitcast(v2, intrinsics.f32x4_ty, ""); - let res = builder - .build_call(intrinsics.maximum_f32x4, &[v1, v2], &state.var_name()) - .try_as_basic_value() - .left() - .unwrap(); + let v1 = canonicalize_nans(builder, intrinsics, v1); + let v2 = canonicalize_nans(builder, intrinsics, v2); + let (v1, v2) = (v1.into_vector_value(), v2.into_vector_value()); + let v1_is_nan = builder.build_float_compare( + FloatPredicate::UNO, + v1, + intrinsics.f32x4_zero, + "nan", + ); + let v2_is_not_nan = builder.build_float_compare( + FloatPredicate::ORD, + v2, + intrinsics.f32x4_zero, + "notnan", + ); + let v1_repr = builder + .build_bitcast(v1, intrinsics.i32x4_ty, "") + .into_vector_value(); + let v2_repr = builder + .build_bitcast(v2, intrinsics.i32x4_ty, "") + .into_vector_value(); + let repr_ne = builder.build_int_compare(IntPredicate::NE, v1_repr, v2_repr, ""); + let float_eq = builder.build_float_compare(FloatPredicate::OEQ, v1, v2, ""); + let min_cmp = builder.build_float_compare(FloatPredicate::OGT, v1, v2, ""); + let zero = splat_vector( + builder, + intrinsics, + intrinsics.f32_zero.as_basic_value_enum(), + intrinsics.f32x4_ty, + "", + ); + let v2 = builder + .build_select( + builder.build_and( + builder.build_and(float_eq, repr_ne, ""), + v2_is_not_nan, + "", + ), + zero, + v2, + "", + ) + .into_vector_value(); + let res = + builder.build_select(builder.build_or(v1_is_nan, min_cmp, ""), v1, v2, ""); let res = builder.build_bitcast(res, intrinsics.i128_ty, ""); state.push1(res); } Operator::F64x2Max => { + // This implements the same logic as LLVM's @llvm.maximum + // intrinsic would, but x86 lowering of that intrinsics + // encounters a fatal error in LLVM 8 and LLVM 9. let (v1, v2) = state.pop2()?; let v1 = builder.build_bitcast(v1, intrinsics.f64x2_ty, ""); let v2 = builder.build_bitcast(v2, intrinsics.f64x2_ty, ""); - let res = builder - .build_call(intrinsics.maximum_f64x2, &[v1, v2], &state.var_name()) - .try_as_basic_value() - .left() - .unwrap(); + let v1 = canonicalize_nans(builder, intrinsics, v1); + let v2 = canonicalize_nans(builder, intrinsics, v2); + let (v1, v2) = (v1.into_vector_value(), v2.into_vector_value()); + let v1_is_nan = builder.build_float_compare( + FloatPredicate::UNO, + v1, + intrinsics.f64x2_zero, + "nan", + ); + let v2_is_not_nan = builder.build_float_compare( + FloatPredicate::ORD, + v2, + intrinsics.f64x2_zero, + "notnan", + ); + let v1_repr = builder + .build_bitcast(v1, intrinsics.i64x2_ty, "") + .into_vector_value(); + let v2_repr = builder + .build_bitcast(v2, intrinsics.i64x2_ty, "") + .into_vector_value(); + let repr_ne = builder.build_int_compare(IntPredicate::NE, v1_repr, v2_repr, ""); + let float_eq = builder.build_float_compare(FloatPredicate::OEQ, v1, v2, ""); + let min_cmp = builder.build_float_compare(FloatPredicate::OGT, v1, v2, ""); + let zero = splat_vector( + builder, + intrinsics, + intrinsics.f64_zero.as_basic_value_enum(), + intrinsics.f64x2_ty, + "", + ); + let v2 = builder + .build_select( + builder.build_and( + builder.build_and(float_eq, repr_ne, ""), + v2_is_not_nan, + "", + ), + zero, + v2, + "", + ) + .into_vector_value(); + let res = + builder.build_select(builder.build_or(v1_is_nan, min_cmp, ""), v1, v2, ""); let res = builder.build_bitcast(res, intrinsics.i128_ty, ""); state.push1(res); } diff --git a/lib/llvm-backend/src/intrinsics.rs b/lib/llvm-backend/src/intrinsics.rs index 278e087bb..afd3bf8ad 100644 --- a/lib/llvm-backend/src/intrinsics.rs +++ b/lib/llvm-backend/src/intrinsics.rs @@ -6,7 +6,9 @@ use inkwell::{ types::{ BasicType, FloatType, FunctionType, IntType, PointerType, StructType, VectorType, VoidType, }, - values::{BasicValue, BasicValueEnum, FloatValue, FunctionValue, IntValue, PointerValue}, + values::{ + BasicValue, BasicValueEnum, FloatValue, FunctionValue, IntValue, PointerValue, VectorValue, + }, AddressSpace, }; use std::collections::HashMap; @@ -125,6 +127,8 @@ pub struct Intrinsics { pub i128_zero: IntValue, pub f32_zero: FloatValue, pub f64_zero: FloatValue, + pub f32x4_zero: VectorValue, + pub f64x2_zero: VectorValue, pub trap_unreachable: BasicValueEnum, pub trap_call_indirect_sig: BasicValueEnum, @@ -191,6 +195,8 @@ impl Intrinsics { let i128_zero = i128_ty.const_int(0, false); let f32_zero = f32_ty.const_float(0.0); let f64_zero = f64_ty.const_float(0.0); + let f32x4_zero = f32x4_ty.const_zero(); + let f64x2_zero = f64x2_ty.const_zero(); let i1_ty_basic = i1_ty.as_basic_type_enum(); let i32_ty_basic = i32_ty.as_basic_type_enum(); @@ -455,6 +461,8 @@ impl Intrinsics { i128_zero, f32_zero, f64_zero, + f32x4_zero, + f64x2_zero, trap_unreachable: i32_zero.as_basic_value_enum(), trap_call_indirect_sig: i32_ty.const_int(1, false).as_basic_value_enum(), diff --git a/lib/runtime-core/src/backing.rs b/lib/runtime-core/src/backing.rs index e69943002..ff21e9195 100644 --- a/lib/runtime-core/src/backing.rs +++ b/lib/runtime-core/src/backing.rs @@ -148,7 +148,7 @@ impl LocalBacking { Initializer::Const(Value::I32(offset)) => offset as u32, Initializer::Const(_) => { return Err(vec![LinkError::Generic { - message: "a const initializer must be the i32 type".to_string(), + message: "a const initializer must be an i32".to_string(), }]); } Initializer::GetGlobal(import_global_index) => { @@ -209,7 +209,7 @@ impl LocalBacking { Initializer::Const(Value::I32(offset)) => offset as u32, Initializer::Const(_) => { return Err(vec![LinkError::Generic { - message: "a const initializer must be the i32 type".to_string(), + message: "a const initializer must be an i32".to_string(), }]); } Initializer::GetGlobal(import_global_index) => { @@ -282,7 +282,7 @@ impl LocalBacking { Initializer::Const(Value::I32(offset)) => offset as u32, Initializer::Const(_) => { return Err(vec![LinkError::Generic { - message: "a const initializer must be the i32 type".to_string(), + message: "a const initializer must be an i32".to_string(), }]); } Initializer::GetGlobal(import_global_index) => { @@ -340,7 +340,7 @@ impl LocalBacking { Initializer::Const(Value::I32(offset)) => offset as u32, Initializer::Const(_) => { return Err(vec![LinkError::Generic { - message: "a const initializer must be the i32 type".to_string(), + message: "a const initializer be an i32".to_string(), }]); } Initializer::GetGlobal(import_global_index) => { diff --git a/lib/spectests/tests/excludes.txt b/lib/spectests/tests/excludes.txt index 56c6a2d56..dee265684 100644 --- a/lib/spectests/tests/excludes.txt +++ b/lib/spectests/tests/excludes.txt @@ -24,7 +24,6 @@ clif:skip:simd_binaryen.wast:* # SIMD not implemented # linking.wast:387,388 appear to be related to WABT issue: https://github.com/pepyakin/wabt-rs/issues/51 -clif:fail:globals.wast:243 # AssertInvalid - Should be invalid clif:fail:linking.wast:137 # AssertTrap - expected trap, got Runtime:Error "unknown trap at 0x106883062 - illegal instruction" clif:fail:linking.wast:139 # AssertTrap - expected trap, got Runtime:Error "unknown trap at 0x106883062 - illegal instruction" clif:fail:linking.wast:142 # AssertTrap - expected trap, got Runtime:Error "unknown trap at 0x106883062 - illegal instruction" @@ -265,577 +264,13 @@ clif:fail:data.wast:266:windows # AssertUnlinkable - caught panic Any clif:fail:data.wast:186:windows # AssertUnlinkable - caught panic Any clif:fail:data.wast:194:windows # AssertUnlinkable - caught panic Any -# LLVM bug with min/max over NaNs -llvm:skip:f32.wast:1651 -llvm:skip:f32.wast:1652 -llvm:skip:f32.wast:1653 -llvm:skip:f32.wast:1654 -llvm:skip:f32.wast:1655 -llvm:skip:f32.wast:1656 -llvm:skip:f32.wast:1657 -llvm:skip:f32.wast:1658 -llvm:skip:f32.wast:1691 -llvm:skip:f32.wast:1692 -llvm:skip:f32.wast:1693 -llvm:skip:f32.wast:1694 -llvm:skip:f32.wast:1695 -llvm:skip:f32.wast:1696 -llvm:skip:f32.wast:1697 -llvm:skip:f32.wast:1698 -llvm:skip:f32.wast:1731 -llvm:skip:f32.wast:1732 -llvm:skip:f32.wast:1733 -llvm:skip:f32.wast:1734 -llvm:skip:f32.wast:1735 -llvm:skip:f32.wast:1736 -llvm:skip:f32.wast:1737 -llvm:skip:f32.wast:1738 -llvm:skip:f32.wast:1771 -llvm:skip:f32.wast:1772 -llvm:skip:f32.wast:1773 -llvm:skip:f32.wast:1774 -llvm:skip:f32.wast:1775 -llvm:skip:f32.wast:1776 -llvm:skip:f32.wast:1777 -llvm:skip:f32.wast:1778 -llvm:skip:f32.wast:1811 -llvm:skip:f32.wast:1812 -llvm:skip:f32.wast:1813 -llvm:skip:f32.wast:1814 -llvm:skip:f32.wast:1815 -llvm:skip:f32.wast:1816 -llvm:skip:f32.wast:1817 -llvm:skip:f32.wast:1818 -llvm:skip:f32.wast:1851 -llvm:skip:f32.wast:1852 -llvm:skip:f32.wast:1853 -llvm:skip:f32.wast:1854 -llvm:skip:f32.wast:1855 -llvm:skip:f32.wast:1856 -llvm:skip:f32.wast:1857 -llvm:skip:f32.wast:1858 -llvm:skip:f32.wast:1891 -llvm:skip:f32.wast:1892 -llvm:skip:f32.wast:1893 -llvm:skip:f32.wast:1894 -llvm:skip:f32.wast:1895 -llvm:skip:f32.wast:1896 -llvm:skip:f32.wast:1897 -llvm:skip:f32.wast:1898 -llvm:skip:f32.wast:1931 -llvm:skip:f32.wast:1932 -llvm:skip:f32.wast:1933 -llvm:skip:f32.wast:1934 -llvm:skip:f32.wast:1935 -llvm:skip:f32.wast:1936 -llvm:skip:f32.wast:1937 -llvm:skip:f32.wast:1938 -llvm:skip:f32.wast:1939 -llvm:skip:f32.wast:1940 -llvm:skip:f32.wast:1941 -llvm:skip:f32.wast:1942 -llvm:skip:f32.wast:1943 -llvm:skip:f32.wast:1944 -llvm:skip:f32.wast:1945 -llvm:skip:f32.wast:1946 -llvm:skip:f32.wast:1947 -llvm:skip:f32.wast:1948 -llvm:skip:f32.wast:1949 -llvm:skip:f32.wast:1950 -llvm:skip:f32.wast:1951 -llvm:skip:f32.wast:1952 -llvm:skip:f32.wast:1953 -llvm:skip:f32.wast:1954 -llvm:skip:f32.wast:1955 -llvm:skip:f32.wast:1956 -llvm:skip:f32.wast:1957 -llvm:skip:f32.wast:1958 -llvm:skip:f32.wast:1959 -llvm:skip:f32.wast:1960 -llvm:skip:f32.wast:1961 -llvm:skip:f32.wast:1962 -llvm:skip:f32.wast:1963 -llvm:skip:f32.wast:1964 -llvm:skip:f32.wast:1965 -llvm:skip:f32.wast:1966 -llvm:skip:f32.wast:1967 -llvm:skip:f32.wast:1968 -llvm:skip:f32.wast:1969 -llvm:skip:f32.wast:1970 -llvm:skip:f32.wast:1971 -llvm:skip:f32.wast:1972 -llvm:skip:f32.wast:1973 -llvm:skip:f32.wast:1974 -llvm:skip:f32.wast:1975 -llvm:skip:f32.wast:1976 -llvm:skip:f32.wast:1977 -llvm:skip:f32.wast:1978 -llvm:skip:f32.wast:1979 -llvm:skip:f32.wast:1980 -llvm:skip:f32.wast:1981 -llvm:skip:f32.wast:1982 -llvm:skip:f32.wast:1983 -llvm:skip:f32.wast:1984 -llvm:skip:f32.wast:1985 -llvm:skip:f32.wast:1986 -llvm:skip:f32.wast:1987 -llvm:skip:f32.wast:1988 -llvm:skip:f32.wast:1989 -llvm:skip:f32.wast:1990 -llvm:skip:f32.wast:1991 -llvm:skip:f32.wast:1992 -llvm:skip:f32.wast:1993 -llvm:skip:f32.wast:1994 -llvm:skip:f32.wast:1995 -llvm:skip:f32.wast:1996 -llvm:skip:f32.wast:1997 -llvm:skip:f32.wast:1998 -llvm:skip:f32.wast:1999 -llvm:skip:f32.wast:2000 -llvm:skip:f32.wast:2001 -llvm:skip:f32.wast:2002 -llvm:skip:f32.wast:2005 -llvm:skip:f32.wast:2006 -llvm:skip:f32.wast:2009 -llvm:skip:f32.wast:2010 -llvm:skip:f32.wast:2013 -llvm:skip:f32.wast:2014 -llvm:skip:f32.wast:2017 -llvm:skip:f32.wast:2018 -llvm:skip:f32.wast:2051 -llvm:skip:f32.wast:2052 -llvm:skip:f32.wast:2053 -llvm:skip:f32.wast:2054 -llvm:skip:f32.wast:2055 -llvm:skip:f32.wast:2056 -llvm:skip:f32.wast:2057 -llvm:skip:f32.wast:2058 -llvm:skip:f32.wast:2091 -llvm:skip:f32.wast:2092 -llvm:skip:f32.wast:2093 -llvm:skip:f32.wast:2094 -llvm:skip:f32.wast:2095 -llvm:skip:f32.wast:2096 -llvm:skip:f32.wast:2097 -llvm:skip:f32.wast:2098 -llvm:skip:f32.wast:2131 -llvm:skip:f32.wast:2132 -llvm:skip:f32.wast:2133 -llvm:skip:f32.wast:2134 -llvm:skip:f32.wast:2135 -llvm:skip:f32.wast:2136 -llvm:skip:f32.wast:2137 -llvm:skip:f32.wast:2138 -llvm:skip:f32.wast:2171 -llvm:skip:f32.wast:2172 -llvm:skip:f32.wast:2173 -llvm:skip:f32.wast:2174 -llvm:skip:f32.wast:2175 -llvm:skip:f32.wast:2176 -llvm:skip:f32.wast:2177 -llvm:skip:f32.wast:2178 -llvm:skip:f32.wast:2211 -llvm:skip:f32.wast:2212 -llvm:skip:f32.wast:2213 -llvm:skip:f32.wast:2214 -llvm:skip:f32.wast:2215 -llvm:skip:f32.wast:2216 -llvm:skip:f32.wast:2217 -llvm:skip:f32.wast:2218 -llvm:skip:f32.wast:2251 -llvm:skip:f32.wast:2252 -llvm:skip:f32.wast:2253 -llvm:skip:f32.wast:2254 -llvm:skip:f32.wast:2255 -llvm:skip:f32.wast:2256 -llvm:skip:f32.wast:2257 -llvm:skip:f32.wast:2258 -llvm:skip:f32.wast:2291 -llvm:skip:f32.wast:2292 -llvm:skip:f32.wast:2293 -llvm:skip:f32.wast:2294 -llvm:skip:f32.wast:2295 -llvm:skip:f32.wast:2296 -llvm:skip:f32.wast:2297 -llvm:skip:f32.wast:2298 -llvm:skip:f32.wast:2331 -llvm:skip:f32.wast:2332 -llvm:skip:f32.wast:2333 -llvm:skip:f32.wast:2334 -llvm:skip:f32.wast:2335 -llvm:skip:f32.wast:2336 -llvm:skip:f32.wast:2337 -llvm:skip:f32.wast:2338 -llvm:skip:f32.wast:2339 -llvm:skip:f32.wast:2340 -llvm:skip:f32.wast:2341 -llvm:skip:f32.wast:2342 -llvm:skip:f32.wast:2343 -llvm:skip:f32.wast:2344 -llvm:skip:f32.wast:2345 -llvm:skip:f32.wast:2346 -llvm:skip:f32.wast:2347 -llvm:skip:f32.wast:2348 -llvm:skip:f32.wast:2349 -llvm:skip:f32.wast:2350 -llvm:skip:f32.wast:2351 -llvm:skip:f32.wast:2352 -llvm:skip:f32.wast:2353 -llvm:skip:f32.wast:2354 -llvm:skip:f32.wast:2355 -llvm:skip:f32.wast:2356 -llvm:skip:f32.wast:2357 -llvm:skip:f32.wast:2358 -llvm:skip:f32.wast:2359 -llvm:skip:f32.wast:2360 -llvm:skip:f32.wast:2361 -llvm:skip:f32.wast:2362 -llvm:skip:f32.wast:2363 -llvm:skip:f32.wast:2364 -llvm:skip:f32.wast:2365 -llvm:skip:f32.wast:2366 -llvm:skip:f32.wast:2367 -llvm:skip:f32.wast:2368 -llvm:skip:f32.wast:2369 -llvm:skip:f32.wast:2370 -llvm:skip:f32.wast:2371 -llvm:skip:f32.wast:2372 -llvm:skip:f32.wast:2373 -llvm:skip:f32.wast:2374 -llvm:skip:f32.wast:2375 -llvm:skip:f32.wast:2376 -llvm:skip:f32.wast:2377 -llvm:skip:f32.wast:2378 -llvm:skip:f32.wast:2379 -llvm:skip:f32.wast:2380 -llvm:skip:f32.wast:2381 -llvm:skip:f32.wast:2382 -llvm:skip:f32.wast:2383 -llvm:skip:f32.wast:2384 -llvm:skip:f32.wast:2385 -llvm:skip:f32.wast:2386 -llvm:skip:f32.wast:2387 -llvm:skip:f32.wast:2388 -llvm:skip:f32.wast:2389 -llvm:skip:f32.wast:2390 -llvm:skip:f32.wast:2391 -llvm:skip:f32.wast:2392 -llvm:skip:f32.wast:2393 -llvm:skip:f32.wast:2394 -llvm:skip:f32.wast:2395 -llvm:skip:f32.wast:2396 -llvm:skip:f32.wast:2397 -llvm:skip:f32.wast:2398 -llvm:skip:f32.wast:2399 -llvm:skip:f32.wast:2400 -llvm:skip:f32.wast:2401 -llvm:skip:f32.wast:2402 -llvm:skip:f32.wast:2403 -llvm:skip:f32.wast:2404 -llvm:skip:f32.wast:2405 -llvm:skip:f32.wast:2406 -llvm:skip:f32.wast:2409 -llvm:skip:f32.wast:2410 -llvm:skip:f32.wast:2413 -llvm:skip:f32.wast:2414 -llvm:skip:f32.wast:2417 -llvm:skip:f32.wast:2418 -llvm:skip:f64.wast:1651 -llvm:skip:f64.wast:1652 -llvm:skip:f64.wast:1653 -llvm:skip:f64.wast:1654 -llvm:skip:f64.wast:1655 -llvm:skip:f64.wast:1656 -llvm:skip:f64.wast:1657 -llvm:skip:f64.wast:1658 -llvm:skip:f64.wast:1691 -llvm:skip:f64.wast:1692 -llvm:skip:f64.wast:1693 -llvm:skip:f64.wast:1694 -llvm:skip:f64.wast:1695 -llvm:skip:f64.wast:1696 -llvm:skip:f64.wast:1697 -llvm:skip:f64.wast:1698 -llvm:skip:f64.wast:1731 -llvm:skip:f64.wast:1732 -llvm:skip:f64.wast:1733 -llvm:skip:f64.wast:1734 -llvm:skip:f64.wast:1735 -llvm:skip:f64.wast:1736 -llvm:skip:f64.wast:1737 -llvm:skip:f64.wast:1738 -llvm:skip:f64.wast:1771 -llvm:skip:f64.wast:1772 -llvm:skip:f64.wast:1773 -llvm:skip:f64.wast:1774 -llvm:skip:f64.wast:1775 -llvm:skip:f64.wast:1776 -llvm:skip:f64.wast:1777 -llvm:skip:f64.wast:1778 -llvm:skip:f64.wast:1811 -llvm:skip:f64.wast:1812 -llvm:skip:f64.wast:1813 -llvm:skip:f64.wast:1814 -llvm:skip:f64.wast:1815 -llvm:skip:f64.wast:1816 -llvm:skip:f64.wast:1817 -llvm:skip:f64.wast:1818 -llvm:skip:f64.wast:1851 -llvm:skip:f64.wast:1852 -llvm:skip:f64.wast:1853 -llvm:skip:f64.wast:1854 -llvm:skip:f64.wast:1855 -llvm:skip:f64.wast:1856 -llvm:skip:f64.wast:1857 -llvm:skip:f64.wast:1858 -llvm:skip:f64.wast:1891 -llvm:skip:f64.wast:1892 -llvm:skip:f64.wast:1893 -llvm:skip:f64.wast:1894 -llvm:skip:f64.wast:1895 -llvm:skip:f64.wast:1896 -llvm:skip:f64.wast:1897 -llvm:skip:f64.wast:1898 -llvm:skip:f64.wast:1931 -llvm:skip:f64.wast:1932 -llvm:skip:f64.wast:1933 -llvm:skip:f64.wast:1934 -llvm:skip:f64.wast:1935 -llvm:skip:f64.wast:1936 -llvm:skip:f64.wast:1937 -llvm:skip:f64.wast:1938 -llvm:skip:f64.wast:1939 -llvm:skip:f64.wast:1940 -llvm:skip:f64.wast:1941 -llvm:skip:f64.wast:1942 -llvm:skip:f64.wast:1943 -llvm:skip:f64.wast:1944 -llvm:skip:f64.wast:1945 -llvm:skip:f64.wast:1946 -llvm:skip:f64.wast:1947 -llvm:skip:f64.wast:1948 -llvm:skip:f64.wast:1949 -llvm:skip:f64.wast:1950 -llvm:skip:f64.wast:1951 -llvm:skip:f64.wast:1952 -llvm:skip:f64.wast:1953 -llvm:skip:f64.wast:1954 -llvm:skip:f64.wast:1955 -llvm:skip:f64.wast:1956 -llvm:skip:f64.wast:1957 -llvm:skip:f64.wast:1958 -llvm:skip:f64.wast:1959 -llvm:skip:f64.wast:1960 -llvm:skip:f64.wast:1961 -llvm:skip:f64.wast:1962 -llvm:skip:f64.wast:1963 -llvm:skip:f64.wast:1964 -llvm:skip:f64.wast:1965 -llvm:skip:f64.wast:1966 -llvm:skip:f64.wast:1967 -llvm:skip:f64.wast:1968 -llvm:skip:f64.wast:1969 -llvm:skip:f64.wast:1970 -llvm:skip:f64.wast:1971 -llvm:skip:f64.wast:1972 -llvm:skip:f64.wast:1973 -llvm:skip:f64.wast:1974 -llvm:skip:f64.wast:1975 -llvm:skip:f64.wast:1976 -llvm:skip:f64.wast:1977 -llvm:skip:f64.wast:1978 -llvm:skip:f64.wast:1979 -llvm:skip:f64.wast:1980 -llvm:skip:f64.wast:1981 -llvm:skip:f64.wast:1982 -llvm:skip:f64.wast:1983 -llvm:skip:f64.wast:1984 -llvm:skip:f64.wast:1985 -llvm:skip:f64.wast:1986 -llvm:skip:f64.wast:1987 -llvm:skip:f64.wast:1988 -llvm:skip:f64.wast:1989 -llvm:skip:f64.wast:1990 -llvm:skip:f64.wast:1991 -llvm:skip:f64.wast:1992 -llvm:skip:f64.wast:1993 -llvm:skip:f64.wast:1994 -llvm:skip:f64.wast:1995 -llvm:skip:f64.wast:1996 -llvm:skip:f64.wast:1997 -llvm:skip:f64.wast:1998 -llvm:skip:f64.wast:1999 -llvm:skip:f64.wast:2000 -llvm:skip:f64.wast:2001 -llvm:skip:f64.wast:2002 -llvm:skip:f64.wast:2005 -llvm:skip:f64.wast:2006 -llvm:skip:f64.wast:2009 -llvm:skip:f64.wast:2010 -llvm:skip:f64.wast:2013 -llvm:skip:f64.wast:2014 -llvm:skip:f64.wast:2017 -llvm:skip:f64.wast:2018 -llvm:skip:f64.wast:2051 -llvm:skip:f64.wast:2052 -llvm:skip:f64.wast:2053 -llvm:skip:f64.wast:2054 -llvm:skip:f64.wast:2055 -llvm:skip:f64.wast:2056 -llvm:skip:f64.wast:2057 -llvm:skip:f64.wast:2058 -llvm:skip:f64.wast:2091 -llvm:skip:f64.wast:2092 -llvm:skip:f64.wast:2093 -llvm:skip:f64.wast:2094 -llvm:skip:f64.wast:2095 -llvm:skip:f64.wast:2096 -llvm:skip:f64.wast:2097 -llvm:skip:f64.wast:2098 -llvm:skip:f64.wast:2131 -llvm:skip:f64.wast:2132 -llvm:skip:f64.wast:2133 -llvm:skip:f64.wast:2134 -llvm:skip:f64.wast:2135 -llvm:skip:f64.wast:2136 -llvm:skip:f64.wast:2137 -llvm:skip:f64.wast:2138 -llvm:skip:f64.wast:2171 -llvm:skip:f64.wast:2172 -llvm:skip:f64.wast:2173 -llvm:skip:f64.wast:2174 -llvm:skip:f64.wast:2175 -llvm:skip:f64.wast:2176 -llvm:skip:f64.wast:2177 -llvm:skip:f64.wast:2178 -llvm:skip:f64.wast:2211 -llvm:skip:f64.wast:2212 -llvm:skip:f64.wast:2213 -llvm:skip:f64.wast:2214 -llvm:skip:f64.wast:2215 -llvm:skip:f64.wast:2216 -llvm:skip:f64.wast:2217 -llvm:skip:f64.wast:2218 -llvm:skip:f64.wast:2251 -llvm:skip:f64.wast:2252 -llvm:skip:f64.wast:2253 -llvm:skip:f64.wast:2254 -llvm:skip:f64.wast:2255 -llvm:skip:f64.wast:2256 -llvm:skip:f64.wast:2257 -llvm:skip:f64.wast:2258 -llvm:skip:f64.wast:2291 -llvm:skip:f64.wast:2292 -llvm:skip:f64.wast:2293 -llvm:skip:f64.wast:2294 -llvm:skip:f64.wast:2295 -llvm:skip:f64.wast:2296 -llvm:skip:f64.wast:2297 -llvm:skip:f64.wast:2298 -llvm:skip:f64.wast:2331 -llvm:skip:f64.wast:2332 -llvm:skip:f64.wast:2333 -llvm:skip:f64.wast:2334 -llvm:skip:f64.wast:2335 -llvm:skip:f64.wast:2336 -llvm:skip:f64.wast:2337 -llvm:skip:f64.wast:2338 -llvm:skip:f64.wast:2339 -llvm:skip:f64.wast:2340 -llvm:skip:f64.wast:2341 -llvm:skip:f64.wast:2342 -llvm:skip:f64.wast:2343 -llvm:skip:f64.wast:2344 -llvm:skip:f64.wast:2345 -llvm:skip:f64.wast:2346 -llvm:skip:f64.wast:2347 -llvm:skip:f64.wast:2348 -llvm:skip:f64.wast:2349 -llvm:skip:f64.wast:2350 -llvm:skip:f64.wast:2351 -llvm:skip:f64.wast:2352 -llvm:skip:f64.wast:2353 -llvm:skip:f64.wast:2354 -llvm:skip:f64.wast:2355 -llvm:skip:f64.wast:2356 -llvm:skip:f64.wast:2357 -llvm:skip:f64.wast:2358 -llvm:skip:f64.wast:2359 -llvm:skip:f64.wast:2360 -llvm:skip:f64.wast:2361 -llvm:skip:f64.wast:2362 -llvm:skip:f64.wast:2363 -llvm:skip:f64.wast:2364 -llvm:skip:f64.wast:2365 -llvm:skip:f64.wast:2366 -llvm:skip:f64.wast:2367 -llvm:skip:f64.wast:2368 -llvm:skip:f64.wast:2369 -llvm:skip:f64.wast:2370 -llvm:skip:f64.wast:2371 -llvm:skip:f64.wast:2372 -llvm:skip:f64.wast:2373 -llvm:skip:f64.wast:2374 -llvm:skip:f64.wast:2375 -llvm:skip:f64.wast:2376 -llvm:skip:f64.wast:2377 -llvm:skip:f64.wast:2378 -llvm:skip:f64.wast:2379 -llvm:skip:f64.wast:2380 -llvm:skip:f64.wast:2381 -llvm:skip:f64.wast:2382 -llvm:skip:f64.wast:2383 -llvm:skip:f64.wast:2384 -llvm:skip:f64.wast:2385 -llvm:skip:f64.wast:2386 -llvm:skip:f64.wast:2387 -llvm:skip:f64.wast:2388 -llvm:skip:f64.wast:2389 -llvm:skip:f64.wast:2390 -llvm:skip:f64.wast:2391 -llvm:skip:f64.wast:2392 -llvm:skip:f64.wast:2393 -llvm:skip:f64.wast:2394 -llvm:skip:f64.wast:2395 -llvm:skip:f64.wast:2396 -llvm:skip:f64.wast:2397 -llvm:skip:f64.wast:2398 -llvm:skip:f64.wast:2399 -llvm:skip:f64.wast:2400 -llvm:skip:f64.wast:2401 -llvm:skip:f64.wast:2402 -llvm:skip:f64.wast:2405 -llvm:skip:f64.wast:2406 -llvm:skip:f64.wast:2409 -llvm:skip:f64.wast:2410 -llvm:skip:f64.wast:2413 -llvm:skip:f64.wast:2414 -llvm:skip:f64.wast:2417 -llvm:skip:f64.wast:2418 - # LLVM -llvm:skip:br_table.wast:1255 -llvm:skip:imports.wast:391 # Running forever -llvm:skip:imports.wast:402 # Running forever -llvm:skip:call.wast:273 # Spec running forever -llvm:skip:call_indirect.wast:556 # Spec running forever -llvm:skip:call_indirect.wast:557 # Spec running forever -llvm:skip:fac.wast:89 # Spec running forever -llvm:skip:skip-stack-guard-page.wast:* # Spec running forever or (signal: 4, SIGILL: illegal instruction) -llvm:skip:linking.wast:236 # terminating with uncaught exception of type WasmTrap -llvm:skip:linking.wast:248 # terminating with uncaught exception of type WasmTrap - llvm:fail:f32.wast:1621 # AssertReturn - result F32(0) ("0x0") does not match expected F32(2147483648) ("0x80000000") llvm:fail:f32.wast:2020 # AssertReturn - result F32(2147483648) ("0x80000000") does not match expected F32(0) ("0x0") llvm:fail:f64.wast:1621 # AssertReturn - result F64(0) ("0x0") does not match expected F64(9223372036854775808) ("0x8000000000000000") llvm:fail:f64.wast:2020 # AssertReturn - result F64(9223372036854775808) ("0x8000000000000000") does not match expected F64(0) ("0x0") -llvm:fail:i32.wast:243 # AssertReturn - result I32(283816271) ("0x10eab14f") does not match expected I32(32) ("0x20") -llvm:fail:i32.wast:252 # AssertReturn - result I32(283816288) ("0x10eab160") does not match expected I32(32) ("0x20") -llvm:fail:i64.wast:243 # AssertReturn - result I64(4578783727) ("0x110eab1ef") does not match expected I64(64) ("0x40") -llvm:fail:i64.wast:252 # AssertReturn - result I64(4578783712) ("0x110eab1e0") does not match expected I64(64) ("0x40") llvm:fail:linking.wast:387 # AssertReturn - result I32(0) ("0x0") does not match expected I32(104) ("0x68") llvm:fail:linking.wast:388 # AssertReturn - Call failed RuntimeError: WebAssembly trap occurred during runtime: incorrect `call_indirect` signature -llvm:fail:load.wast:201 # AssertReturn - result I32(285315103) ("0x1101901f") does not match expected I32(32) ("0x20") # LLVM Windows llvm:skip:address.wast:*:windows diff --git a/src/bin/wasmer.rs b/src/bin/wasmer.rs index 72bc2e8bc..4c51d9770 100644 --- a/src/bin/wasmer.rs +++ b/src/bin/wasmer.rs @@ -23,7 +23,7 @@ use structopt::StructOpt; use wasmer::*; use wasmer_clif_backend::CraneliftCompiler; #[cfg(feature = "backend-llvm")] -use wasmer_llvm_backend::LLVMCompiler; +use wasmer_llvm_backend::{LLVMCompiler, LLVMOptions}; use wasmer_runtime::{ cache::{Cache as BaseCache, FileSystemCache, WasmHash}, Func, Value, VERSION, @@ -109,7 +109,7 @@ pub struct LLVMCLIOptions { post_opt_ir: Option, /// Emit LLVM generated native code object file. - #[structopt(long = "backend-llvm-object-file", parse(from_os_str))] + #[structopt(long = "llvm-object-file", parse(from_os_str))] obj_file: Option, } @@ -405,6 +405,20 @@ fn execute_wasm(options: &Run) -> Result<(), String> { None => return Err("the requested backend is not enabled".into()), }; + #[cfg(feature = "backend-llvm")] + { + if options.backend == Backend::LLVM { + let options = options.backend_llvm_options.clone(); + unsafe { + wasmer_llvm_backend::GLOBAL_OPTIONS = LLVMOptions { + pre_opt_ir: options.pre_opt_ir, + post_opt_ir: options.post_opt_ir, + obj_file: options.obj_file, + } + } + } + } + let track_state = !options.no_track_state; #[cfg(feature = "loader-kernel")]