Merge branch 'master' of github.com:wasmerio/wasmer into simd

This commit is contained in:
Nick Lewycky
2019-07-16 19:16:45 -07:00
56 changed files with 627 additions and 398 deletions

View File

@ -1,18 +1,18 @@
[package]
name = "wasmer-llvm-backend"
version = "0.5.4"
version = "0.5.6"
authors = ["Lachlan Sneff <lachlan.sneff@gmail.com>"]
edition = "2018"
[dependencies]
wasmer-runtime-core = { path = "../runtime-core", version = "0.5.4" }
wasmer-runtime-core = { path = "../runtime-core", version = "0.5.6" }
inkwell = { git = "https://github.com/wasmerio/inkwell", branch = "llvm8-0", features = ["llvm8-0"] }
wasmparser = "0.32.1"
hashbrown = "0.1.8"
smallvec = "0.6.8"
goblin = "0.0.20"
libc = "0.2.49"
nix = "0.13.0"
nix = "0.14.0"
capstone = { version = "0.5.0", optional = true }
[build-dependencies]

View File

@ -185,106 +185,37 @@ fn trunc_sat(
.into_int_value()
}
fn trap_if_not_representatable_as_int(
fn trap_if_not_representable_as_int(
builder: &Builder,
intrinsics: &Intrinsics,
context: &Context,
function: &FunctionValue,
lower_bounds: f64,
lower_bound: f64,
upper_bound: f64,
value: FloatValue,
) {
enum FloatSize {
Bits32,
Bits64,
}
let float_ty = value.get_type();
let lower_bound = float_ty.const_float(lower_bound);
let upper_bound = float_ty.const_float(upper_bound);
// The 'U' in the float predicate is short for "unordered" which means that
// the comparison will compare true if either operand is a NaN. Thus, NaNs
// are out of bounds.
let above_upper_bound_cmp =
builder.build_float_compare(FloatPredicate::UGT, value, upper_bound, "above_upper_bound");
let below_lower_bound_cmp =
builder.build_float_compare(FloatPredicate::ULT, value, lower_bound, "below_lower_bound");
let out_of_bounds = builder.build_or(
above_upper_bound_cmp,
below_lower_bound_cmp,
"out_of_bounds",
);
let failure_block = context.append_basic_block(function, "conversion_failure_block");
let continue_block = context.append_basic_block(function, "conversion_success_block");
let float_ty = value.get_type();
let (int_ty, float_ptr_ty, float_size) = if float_ty == intrinsics.f32_ty {
(intrinsics.i32_ty, intrinsics.f32_ptr_ty, FloatSize::Bits32)
} else if float_ty == intrinsics.f64_ty {
(intrinsics.i64_ty, intrinsics.f64_ptr_ty, FloatSize::Bits64)
} else {
unreachable!()
};
let (exponent, invalid_exponent) = {
let float_bits = {
let space = builder.build_alloca(int_ty, "space");
let float_ptr = builder.build_pointer_cast(space, float_ptr_ty, "float_ptr");
builder.build_store(float_ptr, value);
builder.build_load(space, "float_bits").into_int_value()
};
let (shift_amount, exponent_mask, invalid_exponent) = match float_size {
FloatSize::Bits32 => (23, 0b01111111100000000000000000000000, 0b11111111),
FloatSize::Bits64 => (
52,
0b0111111111110000000000000000000000000000000000000000000000000000,
0b11111111111,
),
};
builder.build_and(
float_bits,
int_ty.const_int(exponent_mask, false),
"masked_bits",
);
(
builder.build_right_shift(
float_bits,
int_ty.const_int(shift_amount, false),
false,
"exponent",
),
invalid_exponent,
)
};
let is_invalid_float = builder.build_or(
builder.build_int_compare(
IntPredicate::EQ,
exponent,
int_ty.const_int(invalid_exponent, false),
"is_not_normal",
),
builder.build_or(
builder.build_float_compare(
FloatPredicate::ULT,
value,
float_ty.const_float(lower_bounds),
"less_than_lower_bounds",
),
builder.build_float_compare(
FloatPredicate::UGT,
value,
float_ty.const_float(upper_bound),
"greater_than_upper_bounds",
),
"float_not_in_bounds",
),
"is_invalid_float",
);
let is_invalid_float = builder
.build_call(
intrinsics.expect_i1,
&[
is_invalid_float.as_basic_value_enum(),
intrinsics.i1_ty.const_int(0, false).as_basic_value_enum(),
],
"is_invalid_float_expect",
)
.try_as_basic_value()
.left()
.unwrap()
.into_int_value();
builder.build_conditional_branch(is_invalid_float, &failure_block, &continue_block);
builder.build_conditional_branch(out_of_bounds, &failure_block, &continue_block);
builder.position_at_end(&failure_block);
builder.build_call(
intrinsics.throw_trap,
@ -3230,7 +3161,7 @@ impl FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator {
}
Operator::I32TruncSF32 => {
let v1 = state.pop1()?.into_float_value();
trap_if_not_representatable_as_int(
trap_if_not_representable_as_int(
builder,
intrinsics,
context,
@ -3245,7 +3176,7 @@ impl FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator {
}
Operator::I32TruncSF64 => {
let v1 = state.pop1()?.into_float_value();
trap_if_not_representatable_as_int(
trap_if_not_representable_as_int(
builder,
intrinsics,
context,
@ -3266,7 +3197,7 @@ impl FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator {
}
Operator::I64TruncSF32 => {
let v1 = state.pop1()?.into_float_value();
trap_if_not_representatable_as_int(
trap_if_not_representable_as_int(
builder,
intrinsics,
context,
@ -3281,7 +3212,7 @@ impl FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator {
}
Operator::I64TruncSF64 => {
let v1 = state.pop1()?.into_float_value();
trap_if_not_representatable_as_int(
trap_if_not_representable_as_int(
builder,
intrinsics,
context,
@ -3302,7 +3233,7 @@ impl FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator {
}
Operator::I32TruncUF32 => {
let v1 = state.pop1()?.into_float_value();
trap_if_not_representatable_as_int(
trap_if_not_representable_as_int(
builder,
intrinsics,
context,
@ -3317,7 +3248,7 @@ impl FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator {
}
Operator::I32TruncUF64 => {
let v1 = state.pop1()?.into_float_value();
trap_if_not_representatable_as_int(
trap_if_not_representable_as_int(
builder,
intrinsics,
context,
@ -3338,7 +3269,7 @@ impl FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator {
}
Operator::I64TruncUF32 => {
let v1 = state.pop1()?.into_float_value();
trap_if_not_representatable_as_int(
trap_if_not_representable_as_int(
builder,
intrinsics,
context,
@ -3353,7 +3284,7 @@ impl FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator {
}
Operator::I64TruncUF64 => {
let v1 = state.pop1()?.into_float_value();
trap_if_not_representatable_as_int(
trap_if_not_representable_as_int(
builder,
intrinsics,
context,
@ -3448,43 +3379,23 @@ impl FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator {
}
Operator::I32ReinterpretF32 => {
let v = state.pop1()?;
let space =
builder.build_alloca(intrinsics.i32_ty.as_basic_type_enum(), &state.var_name());
let f32_space =
builder.build_pointer_cast(space, intrinsics.f32_ptr_ty, &state.var_name());
builder.build_store(f32_space, v);
let int = builder.build_load(space, &state.var_name());
state.push1(int);
let ret = builder.build_bitcast(v, intrinsics.i32_ty, &state.var_name());
state.push1(ret);
}
Operator::I64ReinterpretF64 => {
let v = state.pop1()?;
let space =
builder.build_alloca(intrinsics.i64_ty.as_basic_type_enum(), &state.var_name());
let f64_space =
builder.build_pointer_cast(space, intrinsics.f64_ptr_ty, &state.var_name());
builder.build_store(f64_space, v);
let int = builder.build_load(space, &state.var_name());
state.push1(int);
let ret = builder.build_bitcast(v, intrinsics.i64_ty, &state.var_name());
state.push1(ret);
}
Operator::F32ReinterpretI32 => {
let v = state.pop1()?;
let space =
builder.build_alloca(intrinsics.f32_ty.as_basic_type_enum(), &state.var_name());
let i32_space =
builder.build_pointer_cast(space, intrinsics.i32_ptr_ty, &state.var_name());
builder.build_store(i32_space, v);
let f = builder.build_load(space, &state.var_name());
state.push1(f);
let ret = builder.build_bitcast(v, intrinsics.f32_ty, &state.var_name());
state.push1(ret);
}
Operator::F64ReinterpretI64 => {
let v = state.pop1()?;
let space =
builder.build_alloca(intrinsics.f64_ty.as_basic_type_enum(), &state.var_name());
let i64_space =
builder.build_pointer_cast(space, intrinsics.i64_ptr_ty, &state.var_name());
builder.build_store(i64_space, v);
let f = builder.build_load(space, &state.var_name());
state.push1(f);
let ret = builder.build_bitcast(v, intrinsics.f64_ty, &state.var_name());
state.push1(ret);
}
/***************************
@ -4460,13 +4371,19 @@ impl ModuleCodeGenerator<LLVMFunctionCodeGenerator, LLVMBackend, CodegenError>
if cfg!(test) {
pass_manager.add_verifier_pass();
}
pass_manager.add_function_inlining_pass();
pass_manager.add_promote_memory_to_register_pass();
pass_manager.add_lower_expect_intrinsic_pass();
pass_manager.add_scalar_repl_aggregates_pass();
pass_manager.add_instruction_combining_pass();
pass_manager.add_cfg_simplification_pass();
pass_manager.add_aggressive_inst_combiner_pass();
pass_manager.add_merged_load_store_motion_pass();
pass_manager.add_new_gvn_pass();
pass_manager.add_aggressive_dce_pass();
pass_manager.add_gvn_pass();
pass_manager.add_jump_threading_pass();
pass_manager.add_correlated_value_propagation_pass();
pass_manager.add_sccp_pass();
pass_manager.add_instruction_combining_pass();
pass_manager.add_reassociate_pass();
pass_manager.add_cfg_simplification_pass();
pass_manager.add_bit_tracking_dce_pass();
pass_manager.add_slp_vectorize_pass();
pass_manager.run_on(&self.module);
// self.module.print_to_stderr();