2019-02-14 23:13:58 +00:00
|
|
|
use hashbrown::HashMap;
|
2019-02-12 03:34:04 +00:00
|
|
|
use inkwell::{
|
2019-02-14 23:13:58 +00:00
|
|
|
builder::Builder,
|
2019-02-12 03:34:04 +00:00
|
|
|
context::Context,
|
|
|
|
module::Module,
|
2019-07-02 22:50:33 +00:00
|
|
|
types::{
|
|
|
|
BasicType, FloatType, FunctionType, IntType, PointerType, StructType, VectorType, VoidType,
|
|
|
|
},
|
2019-03-29 09:03:40 +00:00
|
|
|
values::{BasicValue, BasicValueEnum, FloatValue, FunctionValue, IntValue, PointerValue},
|
2019-02-14 23:13:58 +00:00
|
|
|
AddressSpace,
|
|
|
|
};
|
|
|
|
use std::marker::PhantomData;
|
|
|
|
use wasmer_runtime_core::{
|
|
|
|
memory::MemoryType,
|
|
|
|
module::ModuleInfo,
|
|
|
|
structures::TypedIndex,
|
2019-02-23 01:34:55 +00:00
|
|
|
types::{
|
2019-03-08 23:15:16 +00:00
|
|
|
GlobalIndex, ImportedFuncIndex, LocalFuncIndex, LocalOrImport, MemoryIndex, SigIndex,
|
|
|
|
TableIndex, Type,
|
2019-02-23 01:34:55 +00:00
|
|
|
},
|
2019-05-14 10:49:02 +00:00
|
|
|
vm::Ctx,
|
2019-02-12 03:34:04 +00:00
|
|
|
};
|
2019-02-09 23:53:40 +00:00
|
|
|
|
2019-02-15 02:08:20 +00:00
|
|
|
fn type_to_llvm_ptr(intrinsics: &Intrinsics, ty: Type) -> PointerType {
|
|
|
|
match ty {
|
|
|
|
Type::I32 => intrinsics.i32_ptr_ty,
|
|
|
|
Type::I64 => intrinsics.i64_ptr_ty,
|
|
|
|
Type::F32 => intrinsics.f32_ptr_ty,
|
|
|
|
Type::F64 => intrinsics.f64_ptr_ty,
|
2019-07-02 22:01:50 +00:00
|
|
|
Type::V128 => intrinsics.i128_ptr_ty,
|
2019-02-15 02:08:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-09 23:53:40 +00:00
|
|
|
pub struct Intrinsics {
|
|
|
|
pub ctlz_i32: FunctionValue,
|
|
|
|
pub ctlz_i64: FunctionValue,
|
|
|
|
|
|
|
|
pub cttz_i32: FunctionValue,
|
|
|
|
pub cttz_i64: FunctionValue,
|
|
|
|
|
|
|
|
pub ctpop_i32: FunctionValue,
|
|
|
|
pub ctpop_i64: FunctionValue,
|
|
|
|
|
|
|
|
pub sqrt_f32: FunctionValue,
|
|
|
|
pub sqrt_f64: FunctionValue,
|
2019-07-02 22:50:33 +00:00
|
|
|
pub sqrt_f32x4: FunctionValue,
|
|
|
|
pub sqrt_f64x2: FunctionValue,
|
2019-02-09 23:53:40 +00:00
|
|
|
|
|
|
|
pub minimum_f32: FunctionValue,
|
|
|
|
pub minimum_f64: FunctionValue,
|
2019-07-02 22:50:33 +00:00
|
|
|
pub minimum_f32x4: FunctionValue,
|
|
|
|
pub minimum_f64x2: FunctionValue,
|
2019-02-09 23:53:40 +00:00
|
|
|
|
|
|
|
pub maximum_f32: FunctionValue,
|
|
|
|
pub maximum_f64: FunctionValue,
|
2019-07-02 22:50:33 +00:00
|
|
|
pub maximum_f32x4: FunctionValue,
|
|
|
|
pub maximum_f64x2: FunctionValue,
|
2019-02-09 23:53:40 +00:00
|
|
|
|
|
|
|
pub ceil_f32: FunctionValue,
|
|
|
|
pub ceil_f64: FunctionValue,
|
|
|
|
|
|
|
|
pub floor_f32: FunctionValue,
|
|
|
|
pub floor_f64: FunctionValue,
|
|
|
|
|
|
|
|
pub trunc_f32: FunctionValue,
|
|
|
|
pub trunc_f64: FunctionValue,
|
|
|
|
|
|
|
|
pub nearbyint_f32: FunctionValue,
|
|
|
|
pub nearbyint_f64: FunctionValue,
|
|
|
|
|
|
|
|
pub fabs_f32: FunctionValue,
|
|
|
|
pub fabs_f64: FunctionValue,
|
2019-07-02 22:50:33 +00:00
|
|
|
pub fabs_f32x4: FunctionValue,
|
|
|
|
pub fabs_f64x2: FunctionValue,
|
2019-02-09 23:53:40 +00:00
|
|
|
|
|
|
|
pub copysign_f32: FunctionValue,
|
|
|
|
pub copysign_f64: FunctionValue,
|
2019-02-12 03:34:04 +00:00
|
|
|
|
2019-07-02 22:50:33 +00:00
|
|
|
pub sadd_sat_i8x16: FunctionValue,
|
|
|
|
pub sadd_sat_i16x8: FunctionValue,
|
|
|
|
pub uadd_sat_i8x16: FunctionValue,
|
|
|
|
pub uadd_sat_i16x8: FunctionValue,
|
|
|
|
|
|
|
|
pub ssub_sat_i8x16: FunctionValue,
|
|
|
|
pub ssub_sat_i16x8: FunctionValue,
|
|
|
|
pub usub_sat_i8x16: FunctionValue,
|
|
|
|
pub usub_sat_i16x8: FunctionValue,
|
|
|
|
|
2019-02-23 01:34:55 +00:00
|
|
|
pub expect_i1: FunctionValue,
|
2019-02-26 02:07:22 +00:00
|
|
|
pub trap: FunctionValue,
|
2019-02-23 01:34:55 +00:00
|
|
|
|
2019-02-12 03:34:04 +00:00
|
|
|
pub void_ty: VoidType,
|
|
|
|
pub i1_ty: IntType,
|
2019-02-14 23:13:58 +00:00
|
|
|
pub i8_ty: IntType,
|
|
|
|
pub i16_ty: IntType,
|
2019-02-12 03:34:04 +00:00
|
|
|
pub i32_ty: IntType,
|
|
|
|
pub i64_ty: IntType,
|
2019-07-02 22:01:50 +00:00
|
|
|
pub i128_ty: IntType,
|
2019-02-12 03:34:04 +00:00
|
|
|
pub f32_ty: FloatType,
|
|
|
|
pub f64_ty: FloatType,
|
|
|
|
|
2019-07-02 22:50:33 +00:00
|
|
|
pub i1x128_ty: VectorType,
|
|
|
|
pub i8x16_ty: VectorType,
|
|
|
|
pub i16x8_ty: VectorType,
|
|
|
|
pub i32x4_ty: VectorType,
|
|
|
|
pub i64x2_ty: VectorType,
|
|
|
|
pub f32x4_ty: VectorType,
|
|
|
|
pub f64x2_ty: VectorType,
|
|
|
|
|
2019-02-14 23:13:58 +00:00
|
|
|
pub i8_ptr_ty: PointerType,
|
|
|
|
pub i16_ptr_ty: PointerType,
|
|
|
|
pub i32_ptr_ty: PointerType,
|
|
|
|
pub i64_ptr_ty: PointerType,
|
2019-07-02 22:01:50 +00:00
|
|
|
pub i128_ptr_ty: PointerType,
|
2019-02-14 23:13:58 +00:00
|
|
|
pub f32_ptr_ty: PointerType,
|
|
|
|
pub f64_ptr_ty: PointerType,
|
|
|
|
|
2019-02-23 01:34:55 +00:00
|
|
|
pub anyfunc_ty: StructType,
|
|
|
|
|
2019-02-12 03:34:04 +00:00
|
|
|
pub i1_zero: IntValue,
|
|
|
|
pub i32_zero: IntValue,
|
|
|
|
pub i64_zero: IntValue,
|
2019-07-02 22:01:50 +00:00
|
|
|
pub i128_zero: IntValue,
|
2019-02-12 03:34:04 +00:00
|
|
|
pub f32_zero: FloatValue,
|
|
|
|
pub f64_zero: FloatValue,
|
2019-02-13 02:02:00 +00:00
|
|
|
|
2019-03-02 22:16:02 +00:00
|
|
|
pub trap_unreachable: BasicValueEnum,
|
|
|
|
pub trap_call_indirect_sig: BasicValueEnum,
|
2019-03-04 05:38:35 +00:00
|
|
|
pub trap_call_indirect_oob: BasicValueEnum,
|
2019-03-02 22:16:02 +00:00
|
|
|
pub trap_memory_oob: BasicValueEnum,
|
2019-03-05 03:56:02 +00:00
|
|
|
pub trap_illegal_arithmetic: BasicValueEnum,
|
2019-03-02 22:16:02 +00:00
|
|
|
|
2019-02-13 02:02:00 +00:00
|
|
|
// VM intrinsics.
|
|
|
|
pub memory_grow_dynamic_local: FunctionValue,
|
|
|
|
pub memory_grow_static_local: FunctionValue,
|
|
|
|
pub memory_grow_shared_local: FunctionValue,
|
|
|
|
pub memory_grow_dynamic_import: FunctionValue,
|
|
|
|
pub memory_grow_static_import: FunctionValue,
|
|
|
|
pub memory_grow_shared_import: FunctionValue,
|
|
|
|
|
|
|
|
pub memory_size_dynamic_local: FunctionValue,
|
|
|
|
pub memory_size_static_local: FunctionValue,
|
|
|
|
pub memory_size_shared_local: FunctionValue,
|
|
|
|
pub memory_size_dynamic_import: FunctionValue,
|
|
|
|
pub memory_size_static_import: FunctionValue,
|
|
|
|
pub memory_size_shared_import: FunctionValue,
|
2019-02-14 23:13:58 +00:00
|
|
|
|
2019-03-02 22:16:02 +00:00
|
|
|
pub throw_trap: FunctionValue,
|
2019-03-02 20:57:35 +00:00
|
|
|
|
2019-02-14 23:13:58 +00:00
|
|
|
pub ctx_ptr_ty: PointerType,
|
2019-02-09 23:53:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Intrinsics {
|
|
|
|
pub fn declare(module: &Module, context: &Context) -> Self {
|
2019-02-12 03:34:04 +00:00
|
|
|
let void_ty = context.void_type();
|
|
|
|
let i1_ty = context.bool_type();
|
2019-02-14 23:13:58 +00:00
|
|
|
let i8_ty = context.i8_type();
|
|
|
|
let i16_ty = context.i16_type();
|
2019-02-12 03:34:04 +00:00
|
|
|
let i32_ty = context.i32_type();
|
|
|
|
let i64_ty = context.i64_type();
|
2019-07-02 22:01:50 +00:00
|
|
|
let i128_ty = context.i128_type();
|
2019-02-12 03:34:04 +00:00
|
|
|
let f32_ty = context.f32_type();
|
|
|
|
let f64_ty = context.f64_type();
|
2019-02-14 23:13:58 +00:00
|
|
|
|
2019-07-02 22:50:33 +00:00
|
|
|
let i1x128_ty = i1_ty.vec_type(128);
|
|
|
|
let i8x16_ty = i8_ty.vec_type(16);
|
|
|
|
let i16x8_ty = i16_ty.vec_type(8);
|
|
|
|
let i32x4_ty = i32_ty.vec_type(4);
|
|
|
|
let i64x2_ty = i64_ty.vec_type(2);
|
|
|
|
let f32x4_ty = f32_ty.vec_type(4);
|
|
|
|
let f64x2_ty = f64_ty.vec_type(2);
|
|
|
|
|
2019-02-14 23:13:58 +00:00
|
|
|
let i8_ptr_ty = i8_ty.ptr_type(AddressSpace::Generic);
|
|
|
|
let i16_ptr_ty = i16_ty.ptr_type(AddressSpace::Generic);
|
|
|
|
let i32_ptr_ty = i32_ty.ptr_type(AddressSpace::Generic);
|
|
|
|
let i64_ptr_ty = i64_ty.ptr_type(AddressSpace::Generic);
|
2019-07-02 22:01:50 +00:00
|
|
|
let i128_ptr_ty = i128_ty.ptr_type(AddressSpace::Generic);
|
2019-02-14 23:13:58 +00:00
|
|
|
let f32_ptr_ty = f32_ty.ptr_type(AddressSpace::Generic);
|
|
|
|
let f64_ptr_ty = f64_ty.ptr_type(AddressSpace::Generic);
|
|
|
|
|
2019-02-12 03:34:04 +00:00
|
|
|
let i1_zero = i1_ty.const_int(0, false);
|
|
|
|
let i32_zero = i32_ty.const_int(0, false);
|
|
|
|
let i64_zero = i64_ty.const_int(0, false);
|
2019-07-02 22:01:50 +00:00
|
|
|
let i128_zero = i128_ty.const_int(0, false);
|
2019-02-12 03:34:04 +00:00
|
|
|
let f32_zero = f32_ty.const_float(0.0);
|
|
|
|
let f64_zero = f64_ty.const_float(0.0);
|
2019-02-09 23:53:40 +00:00
|
|
|
|
2019-02-12 03:34:04 +00:00
|
|
|
let i1_ty_basic = i1_ty.as_basic_type_enum();
|
|
|
|
let i32_ty_basic = i32_ty.as_basic_type_enum();
|
|
|
|
let i64_ty_basic = i64_ty.as_basic_type_enum();
|
|
|
|
let f32_ty_basic = f32_ty.as_basic_type_enum();
|
|
|
|
let f64_ty_basic = f64_ty.as_basic_type_enum();
|
2019-07-02 22:50:33 +00:00
|
|
|
let i8x16_ty_basic = i8x16_ty.as_basic_type_enum();
|
|
|
|
let i16x8_ty_basic = i16x8_ty.as_basic_type_enum();
|
|
|
|
let f32x4_ty_basic = f32x4_ty.as_basic_type_enum();
|
|
|
|
let f64x2_ty_basic = f64x2_ty.as_basic_type_enum();
|
2019-02-14 23:13:58 +00:00
|
|
|
let i8_ptr_ty_basic = i8_ptr_ty.as_basic_type_enum();
|
|
|
|
|
|
|
|
let ctx_ty = context.opaque_struct_type("ctx");
|
|
|
|
let ctx_ptr_ty = ctx_ty.ptr_type(AddressSpace::Generic);
|
|
|
|
|
|
|
|
let local_memory_ty =
|
2019-02-15 02:08:20 +00:00
|
|
|
context.struct_type(&[i8_ptr_ty_basic, i64_ty_basic, i8_ptr_ty_basic], false);
|
2019-02-14 23:13:58 +00:00
|
|
|
let local_table_ty = local_memory_ty;
|
|
|
|
let local_global_ty = i64_ty;
|
2019-02-15 02:08:20 +00:00
|
|
|
let imported_func_ty =
|
|
|
|
context.struct_type(&[i8_ptr_ty_basic, ctx_ptr_ty.as_basic_type_enum()], false);
|
2019-02-23 01:34:55 +00:00
|
|
|
let sigindex_ty = i32_ty;
|
2019-06-25 23:04:31 +00:00
|
|
|
let rt_intrinsics_ty = i8_ty;
|
2019-05-14 10:49:02 +00:00
|
|
|
let stack_lower_bound_ty = i8_ty;
|
|
|
|
let memory_base_ty = i8_ty;
|
2019-06-25 23:04:31 +00:00
|
|
|
let memory_bound_ty = i8_ty;
|
2019-06-04 18:13:10 +00:00
|
|
|
let internals_ty = i64_ty;
|
2019-06-27 07:49:43 +00:00
|
|
|
let interrupt_signal_mem_ty = i8_ty;
|
2019-03-08 23:15:16 +00:00
|
|
|
let local_function_ty = i8_ptr_ty;
|
2019-02-23 01:34:55 +00:00
|
|
|
|
|
|
|
let anyfunc_ty = context.struct_type(
|
|
|
|
&[
|
|
|
|
i8_ptr_ty_basic,
|
|
|
|
ctx_ptr_ty.as_basic_type_enum(),
|
|
|
|
sigindex_ty.as_basic_type_enum(),
|
|
|
|
],
|
|
|
|
false,
|
|
|
|
);
|
|
|
|
|
2019-02-14 23:13:58 +00:00
|
|
|
ctx_ty.set_body(
|
|
|
|
&[
|
|
|
|
local_memory_ty
|
|
|
|
.ptr_type(AddressSpace::Generic)
|
|
|
|
.ptr_type(AddressSpace::Generic)
|
|
|
|
.as_basic_type_enum(),
|
|
|
|
local_table_ty
|
|
|
|
.ptr_type(AddressSpace::Generic)
|
|
|
|
.ptr_type(AddressSpace::Generic)
|
|
|
|
.as_basic_type_enum(),
|
|
|
|
local_global_ty
|
|
|
|
.ptr_type(AddressSpace::Generic)
|
|
|
|
.ptr_type(AddressSpace::Generic)
|
|
|
|
.as_basic_type_enum(),
|
|
|
|
local_memory_ty
|
|
|
|
.ptr_type(AddressSpace::Generic)
|
|
|
|
.ptr_type(AddressSpace::Generic)
|
|
|
|
.as_basic_type_enum(),
|
|
|
|
local_table_ty
|
|
|
|
.ptr_type(AddressSpace::Generic)
|
|
|
|
.ptr_type(AddressSpace::Generic)
|
|
|
|
.as_basic_type_enum(),
|
|
|
|
local_global_ty
|
|
|
|
.ptr_type(AddressSpace::Generic)
|
|
|
|
.ptr_type(AddressSpace::Generic)
|
|
|
|
.as_basic_type_enum(),
|
|
|
|
imported_func_ty
|
|
|
|
.ptr_type(AddressSpace::Generic)
|
|
|
|
.as_basic_type_enum(),
|
2019-02-23 01:34:55 +00:00
|
|
|
sigindex_ty
|
|
|
|
.ptr_type(AddressSpace::Generic)
|
|
|
|
.as_basic_type_enum(),
|
2019-05-14 10:49:02 +00:00
|
|
|
rt_intrinsics_ty
|
|
|
|
.ptr_type(AddressSpace::Generic)
|
|
|
|
.as_basic_type_enum(),
|
|
|
|
stack_lower_bound_ty
|
|
|
|
.ptr_type(AddressSpace::Generic)
|
|
|
|
.as_basic_type_enum(),
|
|
|
|
memory_base_ty
|
|
|
|
.ptr_type(AddressSpace::Generic)
|
|
|
|
.as_basic_type_enum(),
|
|
|
|
memory_bound_ty
|
|
|
|
.ptr_type(AddressSpace::Generic)
|
|
|
|
.as_basic_type_enum(),
|
2019-06-04 18:13:10 +00:00
|
|
|
internals_ty
|
|
|
|
.ptr_type(AddressSpace::Generic)
|
|
|
|
.as_basic_type_enum(),
|
2019-06-27 07:49:43 +00:00
|
|
|
interrupt_signal_mem_ty
|
|
|
|
.ptr_type(AddressSpace::Generic)
|
|
|
|
.as_basic_type_enum(),
|
2019-03-08 23:15:16 +00:00
|
|
|
local_function_ty
|
|
|
|
.ptr_type(AddressSpace::Generic)
|
|
|
|
.as_basic_type_enum(),
|
2019-02-14 23:13:58 +00:00
|
|
|
],
|
|
|
|
false,
|
|
|
|
);
|
2019-02-09 23:53:40 +00:00
|
|
|
|
2019-07-02 22:50:33 +00:00
|
|
|
let ret_i8x16_take_i8x16_i8x16 = i8x16_ty.fn_type(&[i8x16_ty_basic, i8x16_ty_basic], false);
|
|
|
|
let ret_i16x8_take_i16x8_i16x8 = i16x8_ty.fn_type(&[i16x8_ty_basic, i16x8_ty_basic], false);
|
|
|
|
|
2019-02-12 03:34:04 +00:00
|
|
|
let ret_i32_take_i32_i1 = i32_ty.fn_type(&[i32_ty_basic, i1_ty_basic], false);
|
|
|
|
let ret_i64_take_i64_i1 = i64_ty.fn_type(&[i64_ty_basic, i1_ty_basic], false);
|
2019-02-09 23:53:40 +00:00
|
|
|
|
2019-02-12 03:34:04 +00:00
|
|
|
let ret_i32_take_i32 = i32_ty.fn_type(&[i32_ty_basic], false);
|
|
|
|
let ret_i64_take_i64 = i64_ty.fn_type(&[i64_ty_basic], false);
|
2019-02-09 23:53:40 +00:00
|
|
|
|
2019-02-12 03:34:04 +00:00
|
|
|
let ret_f32_take_f32 = f32_ty.fn_type(&[f32_ty_basic], false);
|
|
|
|
let ret_f64_take_f64 = f64_ty.fn_type(&[f64_ty_basic], false);
|
2019-07-02 22:50:33 +00:00
|
|
|
let ret_f32x4_take_f32x4 = f32x4_ty.fn_type(&[f32x4_ty_basic], false);
|
|
|
|
let ret_f64x2_take_f64x2 = f64x2_ty.fn_type(&[f64x2_ty_basic], false);
|
2019-02-12 03:34:04 +00:00
|
|
|
|
|
|
|
let ret_f32_take_f32_f32 = f32_ty.fn_type(&[f32_ty_basic, f32_ty_basic], false);
|
|
|
|
let ret_f64_take_f64_f64 = f64_ty.fn_type(&[f64_ty_basic, f64_ty_basic], false);
|
2019-07-02 22:50:33 +00:00
|
|
|
let ret_f32x4_take_f32x4_f32x4 = f32x4_ty.fn_type(&[f32x4_ty_basic, f32x4_ty_basic], false);
|
|
|
|
let ret_f64x2_take_f64x2_f64x2 = f64x2_ty.fn_type(&[f64x2_ty_basic, f64x2_ty_basic], false);
|
2019-02-09 23:53:40 +00:00
|
|
|
|
2019-02-15 02:08:20 +00:00
|
|
|
let ret_i32_take_ctx_i32_i32 = i32_ty.fn_type(
|
|
|
|
&[ctx_ptr_ty.as_basic_type_enum(), i32_ty_basic, i32_ty_basic],
|
|
|
|
false,
|
|
|
|
);
|
|
|
|
let ret_i32_take_ctx_i32 =
|
|
|
|
i32_ty.fn_type(&[ctx_ptr_ty.as_basic_type_enum(), i32_ty_basic], false);
|
2019-02-13 02:02:00 +00:00
|
|
|
|
2019-02-23 01:34:55 +00:00
|
|
|
let ret_i1_take_i1_i1 = i1_ty.fn_type(&[i1_ty_basic, i1_ty_basic], false);
|
|
|
|
|
2019-02-09 23:53:40 +00:00
|
|
|
Self {
|
|
|
|
ctlz_i32: module.add_function("llvm.ctlz.i32", ret_i32_take_i32_i1, None),
|
|
|
|
ctlz_i64: module.add_function("llvm.ctlz.i64", ret_i64_take_i64_i1, None),
|
|
|
|
|
|
|
|
cttz_i32: module.add_function("llvm.cttz.i32", ret_i32_take_i32_i1, None),
|
|
|
|
cttz_i64: module.add_function("llvm.cttz.i64", ret_i64_take_i64_i1, None),
|
|
|
|
|
|
|
|
ctpop_i32: module.add_function("llvm.ctpop.i32", ret_i32_take_i32, None),
|
|
|
|
ctpop_i64: module.add_function("llvm.ctpop.i64", ret_i64_take_i64, None),
|
|
|
|
|
|
|
|
sqrt_f32: module.add_function("llvm.sqrt.f32", ret_f32_take_f32, None),
|
|
|
|
sqrt_f64: module.add_function("llvm.sqrt.f64", ret_f64_take_f64, None),
|
2019-07-02 22:50:33 +00:00
|
|
|
sqrt_f32x4: module.add_function("llvm.sqrt.v4f32", ret_f32x4_take_f32x4, None),
|
|
|
|
sqrt_f64x2: module.add_function("llvm.sqrt.v2f64", ret_f64x2_take_f64x2, None),
|
|
|
|
|
|
|
|
minimum_f32: module.add_function("llvm.minnum.f32", ret_f32_take_f32_f32, None),
|
|
|
|
minimum_f64: module.add_function("llvm.minnum.f64", ret_f64_take_f64_f64, None),
|
|
|
|
minimum_f32x4: module.add_function(
|
|
|
|
"llvm.minimum.v4f32",
|
|
|
|
ret_f32x4_take_f32x4_f32x4,
|
|
|
|
None,
|
|
|
|
),
|
|
|
|
minimum_f64x2: module.add_function(
|
|
|
|
"llvm.minimum.v2f64",
|
|
|
|
ret_f64x2_take_f64x2_f64x2,
|
|
|
|
None,
|
|
|
|
),
|
|
|
|
|
|
|
|
maximum_f32: module.add_function("llvm.maxnum.f32", ret_f32_take_f32_f32, None),
|
|
|
|
maximum_f64: module.add_function("llvm.maxnum.f64", ret_f64_take_f64_f64, None),
|
|
|
|
maximum_f32x4: module.add_function(
|
|
|
|
"llvm.maximum.v4f32",
|
|
|
|
ret_f32x4_take_f32x4_f32x4,
|
|
|
|
None,
|
|
|
|
),
|
|
|
|
maximum_f64x2: module.add_function(
|
|
|
|
"llvm.maximum.v2f64",
|
|
|
|
ret_f64x2_take_f64x2_f64x2,
|
|
|
|
None,
|
|
|
|
),
|
2019-02-09 23:53:40 +00:00
|
|
|
|
|
|
|
ceil_f32: module.add_function("llvm.ceil.f32", ret_f32_take_f32, None),
|
|
|
|
ceil_f64: module.add_function("llvm.ceil.f64", ret_f64_take_f64, None),
|
|
|
|
|
|
|
|
floor_f32: module.add_function("llvm.floor.f32", ret_f32_take_f32, None),
|
|
|
|
floor_f64: module.add_function("llvm.floor.f64", ret_f64_take_f64, None),
|
|
|
|
|
|
|
|
trunc_f32: module.add_function("llvm.trunc.f32", ret_f32_take_f32, None),
|
|
|
|
trunc_f64: module.add_function("llvm.trunc.f64", ret_f64_take_f64, None),
|
|
|
|
|
|
|
|
nearbyint_f32: module.add_function("llvm.nearbyint.f32", ret_f32_take_f32, None),
|
|
|
|
nearbyint_f64: module.add_function("llvm.nearbyint.f64", ret_f64_take_f64, None),
|
|
|
|
|
|
|
|
fabs_f32: module.add_function("llvm.fabs.f32", ret_f32_take_f32, None),
|
|
|
|
fabs_f64: module.add_function("llvm.fabs.f64", ret_f64_take_f64, None),
|
2019-07-02 22:50:33 +00:00
|
|
|
fabs_f32x4: module.add_function("llvm.fabs.v4f32", ret_f32x4_take_f32x4, None),
|
|
|
|
fabs_f64x2: module.add_function("llvm.fabs.v2f64", ret_f64x2_take_f64x2, None),
|
2019-02-09 23:53:40 +00:00
|
|
|
|
|
|
|
copysign_f32: module.add_function("llvm.copysign.f32", ret_f32_take_f32_f32, None),
|
|
|
|
copysign_f64: module.add_function("llvm.copysign.f64", ret_f64_take_f64_f64, None),
|
2019-02-12 03:34:04 +00:00
|
|
|
|
2019-07-02 22:50:33 +00:00
|
|
|
sadd_sat_i8x16: module.add_function(
|
|
|
|
"llvm.sadd.sat.v16i8",
|
|
|
|
ret_i8x16_take_i8x16_i8x16,
|
|
|
|
None,
|
|
|
|
),
|
|
|
|
sadd_sat_i16x8: module.add_function(
|
|
|
|
"llvm.sadd.sat.v8i16",
|
|
|
|
ret_i16x8_take_i16x8_i16x8,
|
|
|
|
None,
|
|
|
|
),
|
|
|
|
uadd_sat_i8x16: module.add_function(
|
|
|
|
"llvm.uadd.sat.v16i8",
|
|
|
|
ret_i8x16_take_i8x16_i8x16,
|
|
|
|
None,
|
|
|
|
),
|
|
|
|
uadd_sat_i16x8: module.add_function(
|
|
|
|
"llvm.uadd.sat.v8i16",
|
|
|
|
ret_i16x8_take_i16x8_i16x8,
|
|
|
|
None,
|
|
|
|
),
|
|
|
|
|
|
|
|
ssub_sat_i8x16: module.add_function(
|
|
|
|
"llvm.ssub.sat.v16i8",
|
|
|
|
ret_i8x16_take_i8x16_i8x16,
|
|
|
|
None,
|
|
|
|
),
|
|
|
|
ssub_sat_i16x8: module.add_function(
|
|
|
|
"llvm.ssub.sat.v8i16",
|
|
|
|
ret_i16x8_take_i16x8_i16x8,
|
|
|
|
None,
|
|
|
|
),
|
|
|
|
usub_sat_i8x16: module.add_function(
|
|
|
|
"llvm.usub.sat.v16i8",
|
|
|
|
ret_i8x16_take_i8x16_i8x16,
|
|
|
|
None,
|
|
|
|
),
|
|
|
|
usub_sat_i16x8: module.add_function(
|
|
|
|
"llvm.usub.sat.v8i16",
|
|
|
|
ret_i16x8_take_i16x8_i16x8,
|
|
|
|
None,
|
|
|
|
),
|
|
|
|
|
2019-02-23 01:34:55 +00:00
|
|
|
expect_i1: module.add_function("llvm.expect.i1", ret_i1_take_i1_i1, None),
|
2019-02-26 02:07:22 +00:00
|
|
|
trap: module.add_function("llvm.trap", void_ty.fn_type(&[], false), None),
|
2019-02-23 01:34:55 +00:00
|
|
|
|
2019-02-12 03:34:04 +00:00
|
|
|
void_ty,
|
|
|
|
i1_ty,
|
2019-02-14 23:13:58 +00:00
|
|
|
i8_ty,
|
|
|
|
i16_ty,
|
2019-02-12 03:34:04 +00:00
|
|
|
i32_ty,
|
|
|
|
i64_ty,
|
2019-07-02 22:01:50 +00:00
|
|
|
i128_ty,
|
2019-02-12 03:34:04 +00:00
|
|
|
f32_ty,
|
|
|
|
f64_ty,
|
|
|
|
|
2019-07-02 22:50:33 +00:00
|
|
|
i1x128_ty,
|
|
|
|
i8x16_ty,
|
|
|
|
i16x8_ty,
|
|
|
|
i32x4_ty,
|
|
|
|
i64x2_ty,
|
|
|
|
f32x4_ty,
|
|
|
|
f64x2_ty,
|
|
|
|
|
2019-02-14 23:13:58 +00:00
|
|
|
i8_ptr_ty,
|
|
|
|
i16_ptr_ty,
|
|
|
|
i32_ptr_ty,
|
|
|
|
i64_ptr_ty,
|
2019-07-02 22:01:50 +00:00
|
|
|
i128_ptr_ty,
|
2019-02-14 23:13:58 +00:00
|
|
|
f32_ptr_ty,
|
|
|
|
f64_ptr_ty,
|
|
|
|
|
2019-02-23 01:34:55 +00:00
|
|
|
anyfunc_ty,
|
|
|
|
|
2019-02-12 03:34:04 +00:00
|
|
|
i1_zero,
|
|
|
|
i32_zero,
|
|
|
|
i64_zero,
|
2019-07-02 22:01:50 +00:00
|
|
|
i128_zero,
|
2019-02-12 03:34:04 +00:00
|
|
|
f32_zero,
|
|
|
|
f64_zero,
|
2019-02-13 02:02:00 +00:00
|
|
|
|
2019-03-02 22:16:02 +00:00
|
|
|
trap_unreachable: i32_zero.as_basic_value_enum(),
|
|
|
|
trap_call_indirect_sig: i32_ty.const_int(1, false).as_basic_value_enum(),
|
2019-03-04 05:38:35 +00:00
|
|
|
trap_call_indirect_oob: i32_ty.const_int(3, false).as_basic_value_enum(),
|
2019-03-02 22:16:02 +00:00
|
|
|
trap_memory_oob: i32_ty.const_int(2, false).as_basic_value_enum(),
|
2019-03-05 03:56:02 +00:00
|
|
|
trap_illegal_arithmetic: i32_ty.const_int(4, false).as_basic_value_enum(),
|
2019-03-02 22:16:02 +00:00
|
|
|
|
2019-02-13 02:02:00 +00:00
|
|
|
// VM intrinsics.
|
2019-02-14 23:13:58 +00:00
|
|
|
memory_grow_dynamic_local: module.add_function(
|
|
|
|
"vm.memory.grow.dynamic.local",
|
2019-02-15 02:08:20 +00:00
|
|
|
ret_i32_take_ctx_i32_i32,
|
2019-02-14 23:13:58 +00:00
|
|
|
None,
|
|
|
|
),
|
|
|
|
memory_grow_static_local: module.add_function(
|
|
|
|
"vm.memory.grow.static.local",
|
2019-02-15 02:08:20 +00:00
|
|
|
ret_i32_take_ctx_i32_i32,
|
2019-02-14 23:13:58 +00:00
|
|
|
None,
|
|
|
|
),
|
|
|
|
memory_grow_shared_local: module.add_function(
|
|
|
|
"vm.memory.grow.shared.local",
|
2019-02-15 02:08:20 +00:00
|
|
|
ret_i32_take_ctx_i32_i32,
|
2019-02-14 23:13:58 +00:00
|
|
|
None,
|
|
|
|
),
|
|
|
|
memory_grow_dynamic_import: module.add_function(
|
|
|
|
"vm.memory.grow.dynamic.import",
|
2019-02-15 02:08:20 +00:00
|
|
|
ret_i32_take_ctx_i32_i32,
|
2019-02-14 23:13:58 +00:00
|
|
|
None,
|
|
|
|
),
|
|
|
|
memory_grow_static_import: module.add_function(
|
|
|
|
"vm.memory.grow.static.import",
|
2019-02-15 02:08:20 +00:00
|
|
|
ret_i32_take_ctx_i32_i32,
|
2019-02-14 23:13:58 +00:00
|
|
|
None,
|
|
|
|
),
|
|
|
|
memory_grow_shared_import: module.add_function(
|
|
|
|
"vm.memory.grow.shared.import",
|
2019-02-15 02:08:20 +00:00
|
|
|
ret_i32_take_ctx_i32_i32,
|
2019-02-14 23:13:58 +00:00
|
|
|
None,
|
|
|
|
),
|
|
|
|
|
|
|
|
memory_size_dynamic_local: module.add_function(
|
|
|
|
"vm.memory.size.dynamic.local",
|
2019-02-15 02:08:20 +00:00
|
|
|
ret_i32_take_ctx_i32,
|
2019-02-14 23:13:58 +00:00
|
|
|
None,
|
|
|
|
),
|
|
|
|
memory_size_static_local: module.add_function(
|
|
|
|
"vm.memory.size.static.local",
|
2019-02-15 02:08:20 +00:00
|
|
|
ret_i32_take_ctx_i32,
|
2019-02-14 23:13:58 +00:00
|
|
|
None,
|
|
|
|
),
|
|
|
|
memory_size_shared_local: module.add_function(
|
|
|
|
"vm.memory.size.shared.local",
|
2019-02-15 02:08:20 +00:00
|
|
|
ret_i32_take_ctx_i32,
|
2019-02-14 23:13:58 +00:00
|
|
|
None,
|
|
|
|
),
|
|
|
|
memory_size_dynamic_import: module.add_function(
|
|
|
|
"vm.memory.size.dynamic.import",
|
2019-02-15 02:08:20 +00:00
|
|
|
ret_i32_take_ctx_i32,
|
2019-02-14 23:13:58 +00:00
|
|
|
None,
|
|
|
|
),
|
|
|
|
memory_size_static_import: module.add_function(
|
|
|
|
"vm.memory.size.static.import",
|
2019-02-15 02:08:20 +00:00
|
|
|
ret_i32_take_ctx_i32,
|
2019-02-14 23:13:58 +00:00
|
|
|
None,
|
|
|
|
),
|
|
|
|
memory_size_shared_import: module.add_function(
|
|
|
|
"vm.memory.size.shared.import",
|
2019-02-15 02:08:20 +00:00
|
|
|
ret_i32_take_ctx_i32,
|
2019-02-14 23:13:58 +00:00
|
|
|
None,
|
|
|
|
),
|
2019-03-02 22:16:02 +00:00
|
|
|
throw_trap: module.add_function(
|
|
|
|
"vm.exception.trap",
|
|
|
|
void_ty.fn_type(&[i32_ty_basic], false),
|
2019-03-02 20:57:35 +00:00
|
|
|
None,
|
|
|
|
),
|
2019-02-14 23:13:58 +00:00
|
|
|
ctx_ptr_ty,
|
|
|
|
}
|
|
|
|
}
|
2019-02-09 23:53:40 +00:00
|
|
|
}
|
2019-02-13 02:02:00 +00:00
|
|
|
|
2019-03-04 05:56:30 +00:00
|
|
|
#[derive(Clone, Copy)]
|
|
|
|
pub enum MemoryCache {
|
2019-02-14 23:13:58 +00:00
|
|
|
/// The memory moves around.
|
|
|
|
Dynamic {
|
|
|
|
ptr_to_base_ptr: PointerValue,
|
|
|
|
ptr_to_bounds: PointerValue,
|
|
|
|
},
|
|
|
|
/// The memory is always in the same place.
|
|
|
|
Static {
|
|
|
|
base_ptr: PointerValue,
|
|
|
|
bounds: IntValue,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2019-02-15 02:08:20 +00:00
|
|
|
struct TableCache {
|
|
|
|
ptr_to_base_ptr: PointerValue,
|
|
|
|
ptr_to_bounds: PointerValue,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Copy)]
|
|
|
|
pub enum GlobalCache {
|
|
|
|
Mut { ptr_to_value: PointerValue },
|
2019-03-04 23:51:45 +00:00
|
|
|
Const { value: BasicValueEnum },
|
2019-02-15 02:08:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct ImportedFuncCache {
|
|
|
|
func_ptr: PointerValue,
|
|
|
|
ctx_ptr: PointerValue,
|
|
|
|
}
|
|
|
|
|
2019-02-14 23:13:58 +00:00
|
|
|
pub struct CtxType<'a> {
|
|
|
|
ctx_ptr_value: PointerValue,
|
|
|
|
|
|
|
|
info: &'a ModuleInfo,
|
2019-03-04 05:13:37 +00:00
|
|
|
cache_builder: Builder,
|
2019-02-14 23:13:58 +00:00
|
|
|
|
|
|
|
cached_memories: HashMap<MemoryIndex, MemoryCache>,
|
2019-02-15 02:08:20 +00:00
|
|
|
cached_tables: HashMap<TableIndex, TableCache>,
|
2019-02-23 01:34:55 +00:00
|
|
|
cached_sigindices: HashMap<SigIndex, IntValue>,
|
2019-02-15 02:08:20 +00:00
|
|
|
cached_globals: HashMap<GlobalIndex, GlobalCache>,
|
|
|
|
cached_imported_functions: HashMap<ImportedFuncIndex, ImportedFuncCache>,
|
2019-02-14 23:13:58 +00:00
|
|
|
|
|
|
|
_phantom: PhantomData<&'a FunctionValue>,
|
|
|
|
}
|
|
|
|
|
2019-05-14 10:49:02 +00:00
|
|
|
fn offset_to_index(offset: u8) -> u32 {
|
|
|
|
(offset as usize / ::std::mem::size_of::<usize>()) as u32
|
|
|
|
}
|
|
|
|
|
2019-02-14 23:13:58 +00:00
|
|
|
impl<'a> CtxType<'a> {
|
2019-05-07 11:20:18 +00:00
|
|
|
pub fn new(
|
|
|
|
info: &'a ModuleInfo,
|
|
|
|
func_value: &'a FunctionValue,
|
|
|
|
cache_builder: Builder,
|
|
|
|
) -> CtxType<'a> {
|
|
|
|
CtxType {
|
|
|
|
ctx_ptr_value: func_value.get_nth_param(0).unwrap().into_pointer_value(),
|
|
|
|
|
|
|
|
info,
|
|
|
|
cache_builder,
|
|
|
|
|
|
|
|
cached_memories: HashMap::new(),
|
|
|
|
cached_tables: HashMap::new(),
|
|
|
|
cached_sigindices: HashMap::new(),
|
|
|
|
cached_globals: HashMap::new(),
|
|
|
|
cached_imported_functions: HashMap::new(),
|
|
|
|
|
|
|
|
_phantom: PhantomData,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-14 23:13:58 +00:00
|
|
|
pub fn basic(&self) -> BasicValueEnum {
|
|
|
|
self.ctx_ptr_value.as_basic_value_enum()
|
|
|
|
}
|
|
|
|
|
2019-05-07 11:20:18 +00:00
|
|
|
pub fn memory(&mut self, index: MemoryIndex, intrinsics: &Intrinsics) -> MemoryCache {
|
|
|
|
let (cached_memories, info, ctx_ptr_value, cache_builder) = (
|
2019-02-14 23:13:58 +00:00
|
|
|
&mut self.cached_memories,
|
|
|
|
self.info,
|
|
|
|
self.ctx_ptr_value,
|
2019-03-04 05:13:37 +00:00
|
|
|
&self.cache_builder,
|
2019-02-14 23:13:58 +00:00
|
|
|
);
|
|
|
|
|
2019-03-04 05:56:30 +00:00
|
|
|
*cached_memories.entry(index).or_insert_with(|| {
|
2019-02-14 23:13:58 +00:00
|
|
|
let (memory_array_ptr_ptr, index, memory_type) = match index.local_or_import(info) {
|
|
|
|
LocalOrImport::Local(local_mem_index) => (
|
2019-03-04 05:13:37 +00:00
|
|
|
unsafe {
|
2019-05-14 10:49:02 +00:00
|
|
|
cache_builder.build_struct_gep(
|
|
|
|
ctx_ptr_value,
|
|
|
|
offset_to_index(Ctx::offset_memories()),
|
|
|
|
"memory_array_ptr_ptr",
|
|
|
|
)
|
2019-03-04 05:13:37 +00:00
|
|
|
},
|
2019-02-14 23:13:58 +00:00
|
|
|
local_mem_index.index() as u64,
|
|
|
|
info.memories[local_mem_index].memory_type(),
|
|
|
|
),
|
|
|
|
LocalOrImport::Import(import_mem_index) => (
|
2019-03-04 05:13:37 +00:00
|
|
|
unsafe {
|
2019-05-14 10:49:02 +00:00
|
|
|
cache_builder.build_struct_gep(
|
|
|
|
ctx_ptr_value,
|
|
|
|
offset_to_index(Ctx::offset_imported_memories()),
|
|
|
|
"memory_array_ptr_ptr",
|
|
|
|
)
|
2019-03-04 05:13:37 +00:00
|
|
|
},
|
2019-02-14 23:13:58 +00:00
|
|
|
import_mem_index.index() as u64,
|
|
|
|
info.imported_memories[import_mem_index].1.memory_type(),
|
|
|
|
),
|
|
|
|
};
|
|
|
|
|
2019-03-04 05:13:37 +00:00
|
|
|
let memory_array_ptr = cache_builder
|
2019-02-14 23:13:58 +00:00
|
|
|
.build_load(memory_array_ptr_ptr, "memory_array_ptr")
|
|
|
|
.into_pointer_value();
|
|
|
|
let const_index = intrinsics.i32_ty.const_int(index, false);
|
|
|
|
let memory_ptr_ptr = unsafe {
|
2019-03-04 05:13:37 +00:00
|
|
|
cache_builder.build_in_bounds_gep(
|
|
|
|
memory_array_ptr,
|
|
|
|
&[const_index],
|
|
|
|
"memory_ptr_ptr",
|
|
|
|
)
|
2019-02-14 23:13:58 +00:00
|
|
|
};
|
2019-03-04 05:13:37 +00:00
|
|
|
let memory_ptr = cache_builder
|
2019-02-14 23:13:58 +00:00
|
|
|
.build_load(memory_ptr_ptr, "memory_ptr")
|
|
|
|
.into_pointer_value();
|
|
|
|
|
|
|
|
let (ptr_to_base_ptr, ptr_to_bounds) = unsafe {
|
|
|
|
(
|
2019-03-04 05:13:37 +00:00
|
|
|
cache_builder.build_struct_gep(memory_ptr, 0, "base_ptr"),
|
|
|
|
cache_builder.build_struct_gep(memory_ptr, 1, "bounds_ptr"),
|
2019-02-14 23:13:58 +00:00
|
|
|
)
|
|
|
|
};
|
|
|
|
|
|
|
|
match memory_type {
|
|
|
|
MemoryType::Dynamic => MemoryCache::Dynamic {
|
|
|
|
ptr_to_base_ptr,
|
|
|
|
ptr_to_bounds,
|
|
|
|
},
|
|
|
|
MemoryType::Static | MemoryType::SharedStatic => MemoryCache::Static {
|
2019-03-04 05:13:37 +00:00
|
|
|
base_ptr: cache_builder
|
2019-02-14 23:13:58 +00:00
|
|
|
.build_load(ptr_to_base_ptr, "base")
|
|
|
|
.into_pointer_value(),
|
2019-03-04 05:13:37 +00:00
|
|
|
bounds: cache_builder
|
|
|
|
.build_load(ptr_to_bounds, "bounds")
|
|
|
|
.into_int_value(),
|
2019-02-14 23:13:58 +00:00
|
|
|
},
|
|
|
|
}
|
2019-03-04 05:56:30 +00:00
|
|
|
})
|
2019-02-14 23:13:58 +00:00
|
|
|
}
|
2019-02-15 02:08:20 +00:00
|
|
|
|
2019-05-07 11:20:18 +00:00
|
|
|
pub fn table(
|
|
|
|
&mut self,
|
|
|
|
index: TableIndex,
|
|
|
|
intrinsics: &Intrinsics,
|
|
|
|
builder: &Builder,
|
|
|
|
) -> (PointerValue, IntValue) {
|
|
|
|
let (cached_tables, info, ctx_ptr_value, cache_builder) = (
|
2019-02-23 01:34:55 +00:00
|
|
|
&mut self.cached_tables,
|
|
|
|
self.info,
|
|
|
|
self.ctx_ptr_value,
|
2019-03-04 05:13:37 +00:00
|
|
|
&self.cache_builder,
|
2019-02-23 01:34:55 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
let TableCache {
|
|
|
|
ptr_to_base_ptr,
|
|
|
|
ptr_to_bounds,
|
|
|
|
} = *cached_tables.entry(index).or_insert_with(|| {
|
|
|
|
let (table_array_ptr_ptr, index) = match index.local_or_import(info) {
|
|
|
|
LocalOrImport::Local(local_table_index) => (
|
2019-03-04 05:13:37 +00:00
|
|
|
unsafe {
|
2019-05-14 10:49:02 +00:00
|
|
|
cache_builder.build_struct_gep(
|
|
|
|
ctx_ptr_value,
|
|
|
|
offset_to_index(Ctx::offset_tables()),
|
|
|
|
"table_array_ptr_ptr",
|
|
|
|
)
|
2019-03-04 05:13:37 +00:00
|
|
|
},
|
2019-02-23 01:34:55 +00:00
|
|
|
local_table_index.index() as u64,
|
|
|
|
),
|
|
|
|
LocalOrImport::Import(import_table_index) => (
|
2019-03-04 05:13:37 +00:00
|
|
|
unsafe {
|
2019-05-14 10:49:02 +00:00
|
|
|
cache_builder.build_struct_gep(
|
|
|
|
ctx_ptr_value,
|
|
|
|
offset_to_index(Ctx::offset_imported_tables()),
|
|
|
|
"table_array_ptr_ptr",
|
|
|
|
)
|
2019-03-04 05:13:37 +00:00
|
|
|
},
|
2019-02-23 01:34:55 +00:00
|
|
|
import_table_index.index() as u64,
|
|
|
|
),
|
|
|
|
};
|
|
|
|
|
2019-03-04 05:13:37 +00:00
|
|
|
let table_array_ptr = cache_builder
|
2019-02-23 01:34:55 +00:00
|
|
|
.build_load(table_array_ptr_ptr, "table_array_ptr")
|
|
|
|
.into_pointer_value();
|
|
|
|
let const_index = intrinsics.i32_ty.const_int(index, false);
|
|
|
|
let table_ptr_ptr = unsafe {
|
2019-03-04 05:13:37 +00:00
|
|
|
cache_builder.build_in_bounds_gep(table_array_ptr, &[const_index], "table_ptr_ptr")
|
2019-02-23 01:34:55 +00:00
|
|
|
};
|
2019-03-04 05:13:37 +00:00
|
|
|
let table_ptr = cache_builder
|
2019-02-23 01:34:55 +00:00
|
|
|
.build_load(table_ptr_ptr, "table_ptr")
|
|
|
|
.into_pointer_value();
|
|
|
|
|
|
|
|
let (ptr_to_base_ptr, ptr_to_bounds) = unsafe {
|
|
|
|
(
|
2019-03-04 05:13:37 +00:00
|
|
|
cache_builder.build_struct_gep(table_ptr, 0, "base_ptr"),
|
|
|
|
cache_builder.build_struct_gep(table_ptr, 1, "bounds_ptr"),
|
2019-02-23 01:34:55 +00:00
|
|
|
)
|
|
|
|
};
|
|
|
|
|
|
|
|
TableCache {
|
|
|
|
ptr_to_base_ptr,
|
|
|
|
ptr_to_bounds,
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
(
|
|
|
|
builder
|
|
|
|
.build_load(ptr_to_base_ptr, "base_ptr")
|
|
|
|
.into_pointer_value(),
|
|
|
|
builder.build_load(ptr_to_bounds, "bounds").into_int_value(),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2019-05-07 11:20:18 +00:00
|
|
|
pub fn local_func(
|
|
|
|
&mut self,
|
|
|
|
index: LocalFuncIndex,
|
|
|
|
fn_ty: FunctionType,
|
|
|
|
intrinsics: &Intrinsics,
|
|
|
|
builder: &Builder,
|
|
|
|
) -> PointerValue {
|
2019-05-14 10:49:02 +00:00
|
|
|
let local_func_array_ptr_ptr = unsafe {
|
|
|
|
builder.build_struct_gep(
|
|
|
|
self.ctx_ptr_value,
|
|
|
|
offset_to_index(Ctx::offset_local_functions()),
|
|
|
|
"local_func_array_ptr_ptr",
|
|
|
|
)
|
|
|
|
};
|
2019-05-07 11:20:18 +00:00
|
|
|
let local_func_array_ptr = builder
|
2019-03-08 23:15:16 +00:00
|
|
|
.build_load(local_func_array_ptr_ptr, "local_func_array_ptr")
|
|
|
|
.into_pointer_value();
|
|
|
|
let local_func_ptr_ptr = unsafe {
|
2019-05-07 11:20:18 +00:00
|
|
|
builder.build_in_bounds_gep(
|
2019-03-08 23:15:16 +00:00
|
|
|
local_func_array_ptr,
|
2019-05-07 11:20:18 +00:00
|
|
|
&[intrinsics.i32_ty.const_int(index.index() as u64, false)],
|
2019-03-08 23:15:16 +00:00
|
|
|
"local_func_ptr_ptr",
|
|
|
|
)
|
|
|
|
};
|
2019-05-07 11:20:18 +00:00
|
|
|
let local_func_ptr = builder
|
2019-03-08 23:15:16 +00:00
|
|
|
.build_load(local_func_ptr_ptr, "local_func_ptr")
|
|
|
|
.into_pointer_value();
|
2019-05-07 11:20:18 +00:00
|
|
|
builder.build_pointer_cast(
|
2019-03-08 23:15:16 +00:00
|
|
|
local_func_ptr,
|
|
|
|
fn_ty.ptr_type(AddressSpace::Generic),
|
|
|
|
"local_func_ptr",
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2019-05-07 11:20:18 +00:00
|
|
|
pub fn dynamic_sigindex(&mut self, index: SigIndex, intrinsics: &Intrinsics) -> IntValue {
|
|
|
|
let (cached_sigindices, ctx_ptr_value, cache_builder) = (
|
2019-02-23 01:34:55 +00:00
|
|
|
&mut self.cached_sigindices,
|
|
|
|
self.ctx_ptr_value,
|
2019-03-04 05:13:37 +00:00
|
|
|
&self.cache_builder,
|
2019-02-23 01:34:55 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
*cached_sigindices.entry(index).or_insert_with(|| {
|
2019-03-04 05:13:37 +00:00
|
|
|
let sigindex_array_ptr_ptr = unsafe {
|
2019-05-14 10:49:02 +00:00
|
|
|
cache_builder.build_struct_gep(
|
|
|
|
ctx_ptr_value,
|
|
|
|
offset_to_index(Ctx::offset_signatures()),
|
|
|
|
"sigindex_array_ptr_ptr",
|
|
|
|
)
|
2019-03-04 05:13:37 +00:00
|
|
|
};
|
|
|
|
let sigindex_array_ptr = cache_builder
|
2019-02-23 01:34:55 +00:00
|
|
|
.build_load(sigindex_array_ptr_ptr, "sigindex_array_ptr")
|
|
|
|
.into_pointer_value();
|
|
|
|
let const_index = intrinsics.i32_ty.const_int(index.index() as u64, false);
|
|
|
|
|
|
|
|
let sigindex_ptr = unsafe {
|
2019-03-04 05:13:37 +00:00
|
|
|
cache_builder.build_in_bounds_gep(
|
|
|
|
sigindex_array_ptr,
|
|
|
|
&[const_index],
|
|
|
|
"sigindex_ptr",
|
|
|
|
)
|
2019-02-23 01:34:55 +00:00
|
|
|
};
|
|
|
|
|
2019-03-04 05:13:37 +00:00
|
|
|
cache_builder
|
2019-02-23 01:34:55 +00:00
|
|
|
.build_load(sigindex_ptr, "sigindex")
|
|
|
|
.into_int_value()
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-05-07 11:20:18 +00:00
|
|
|
pub fn global_cache(&mut self, index: GlobalIndex, intrinsics: &Intrinsics) -> GlobalCache {
|
|
|
|
let (cached_globals, ctx_ptr_value, info, cache_builder) = (
|
2019-02-15 02:08:20 +00:00
|
|
|
&mut self.cached_globals,
|
|
|
|
self.ctx_ptr_value,
|
|
|
|
self.info,
|
2019-03-04 05:13:37 +00:00
|
|
|
&self.cache_builder,
|
2019-02-15 02:08:20 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
*cached_globals.entry(index).or_insert_with(|| {
|
|
|
|
let (globals_array_ptr_ptr, index, mutable, wasmer_ty) =
|
|
|
|
match index.local_or_import(info) {
|
|
|
|
LocalOrImport::Local(local_global_index) => {
|
|
|
|
let desc = info.globals[local_global_index].desc;
|
|
|
|
(
|
|
|
|
unsafe {
|
2019-03-04 05:13:37 +00:00
|
|
|
cache_builder.build_struct_gep(
|
|
|
|
ctx_ptr_value,
|
2019-05-14 10:49:02 +00:00
|
|
|
offset_to_index(Ctx::offset_globals()),
|
2019-03-04 05:13:37 +00:00
|
|
|
"globals_array_ptr_ptr",
|
|
|
|
)
|
2019-02-15 02:08:20 +00:00
|
|
|
},
|
|
|
|
local_global_index.index() as u64,
|
|
|
|
desc.mutable,
|
|
|
|
desc.ty,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
LocalOrImport::Import(import_global_index) => {
|
|
|
|
let desc = info.imported_globals[import_global_index].1;
|
|
|
|
(
|
|
|
|
unsafe {
|
2019-03-04 05:13:37 +00:00
|
|
|
cache_builder.build_struct_gep(
|
|
|
|
ctx_ptr_value,
|
2019-05-14 10:49:02 +00:00
|
|
|
offset_to_index(Ctx::offset_imported_globals()),
|
2019-03-04 05:13:37 +00:00
|
|
|
"globals_array_ptr_ptr",
|
|
|
|
)
|
2019-02-15 02:08:20 +00:00
|
|
|
},
|
|
|
|
import_global_index.index() as u64,
|
|
|
|
desc.mutable,
|
|
|
|
desc.ty,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let llvm_ptr_ty = type_to_llvm_ptr(intrinsics, wasmer_ty);
|
|
|
|
|
2019-03-04 05:13:37 +00:00
|
|
|
let global_array_ptr = cache_builder
|
2019-02-15 02:08:20 +00:00
|
|
|
.build_load(globals_array_ptr_ptr, "global_array_ptr")
|
|
|
|
.into_pointer_value();
|
|
|
|
let const_index = intrinsics.i32_ty.const_int(index, false);
|
|
|
|
let global_ptr_ptr = unsafe {
|
2019-03-04 05:13:37 +00:00
|
|
|
cache_builder.build_in_bounds_gep(
|
|
|
|
global_array_ptr,
|
|
|
|
&[const_index],
|
|
|
|
"global_ptr_ptr",
|
|
|
|
)
|
2019-02-15 02:08:20 +00:00
|
|
|
};
|
2019-03-04 05:13:37 +00:00
|
|
|
let global_ptr = cache_builder
|
2019-02-15 02:08:20 +00:00
|
|
|
.build_load(global_ptr_ptr, "global_ptr")
|
|
|
|
.into_pointer_value();
|
|
|
|
|
2019-03-04 23:51:45 +00:00
|
|
|
let global_ptr_typed =
|
|
|
|
cache_builder.build_pointer_cast(global_ptr, llvm_ptr_ty, "global_ptr_typed");
|
2019-02-15 02:08:20 +00:00
|
|
|
|
|
|
|
if mutable {
|
|
|
|
GlobalCache::Mut {
|
|
|
|
ptr_to_value: global_ptr_typed,
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
GlobalCache::Const {
|
2019-03-04 23:51:45 +00:00
|
|
|
value: cache_builder.build_load(global_ptr_typed, "global_value"),
|
2019-02-15 02:08:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-05-07 11:20:18 +00:00
|
|
|
pub fn imported_func(
|
|
|
|
&mut self,
|
|
|
|
index: ImportedFuncIndex,
|
|
|
|
intrinsics: &Intrinsics,
|
|
|
|
) -> (PointerValue, PointerValue) {
|
|
|
|
let (cached_imported_functions, ctx_ptr_value, cache_builder) = (
|
2019-02-15 02:08:20 +00:00
|
|
|
&mut self.cached_imported_functions,
|
|
|
|
self.ctx_ptr_value,
|
2019-03-04 05:13:37 +00:00
|
|
|
&self.cache_builder,
|
2019-02-15 02:08:20 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
let imported_func_cache = cached_imported_functions.entry(index).or_insert_with(|| {
|
|
|
|
let func_array_ptr_ptr = unsafe {
|
2019-05-14 10:49:02 +00:00
|
|
|
cache_builder.build_struct_gep(
|
|
|
|
ctx_ptr_value,
|
|
|
|
offset_to_index(Ctx::offset_imported_funcs()),
|
|
|
|
"imported_func_array_ptr_ptr",
|
|
|
|
)
|
2019-02-15 02:08:20 +00:00
|
|
|
};
|
2019-03-04 05:13:37 +00:00
|
|
|
let func_array_ptr = cache_builder
|
2019-02-15 02:08:20 +00:00
|
|
|
.build_load(func_array_ptr_ptr, "func_array_ptr")
|
|
|
|
.into_pointer_value();
|
|
|
|
let const_index = intrinsics.i32_ty.const_int(index.index() as u64, false);
|
2019-03-04 22:41:56 +00:00
|
|
|
let imported_func_ptr = unsafe {
|
2019-03-04 05:13:37 +00:00
|
|
|
cache_builder.build_in_bounds_gep(
|
|
|
|
func_array_ptr,
|
|
|
|
&[const_index],
|
2019-03-04 22:41:56 +00:00
|
|
|
"imported_func_ptr",
|
2019-03-04 05:13:37 +00:00
|
|
|
)
|
2019-02-15 02:08:20 +00:00
|
|
|
};
|
|
|
|
let (func_ptr_ptr, ctx_ptr_ptr) = unsafe {
|
|
|
|
(
|
2019-03-04 05:13:37 +00:00
|
|
|
cache_builder.build_struct_gep(imported_func_ptr, 0, "func_ptr_ptr"),
|
|
|
|
cache_builder.build_struct_gep(imported_func_ptr, 1, "ctx_ptr_ptr"),
|
2019-02-15 02:08:20 +00:00
|
|
|
)
|
|
|
|
};
|
|
|
|
|
2019-03-04 05:13:37 +00:00
|
|
|
let func_ptr = cache_builder
|
2019-02-15 02:08:20 +00:00
|
|
|
.build_load(func_ptr_ptr, "func_ptr")
|
|
|
|
.into_pointer_value();
|
2019-03-04 05:13:37 +00:00
|
|
|
let ctx_ptr = cache_builder
|
2019-02-15 02:08:20 +00:00
|
|
|
.build_load(ctx_ptr_ptr, "ctx_ptr")
|
|
|
|
.into_pointer_value();
|
|
|
|
|
|
|
|
ImportedFuncCache { func_ptr, ctx_ptr }
|
|
|
|
});
|
|
|
|
|
|
|
|
(imported_func_cache.func_ptr, imported_func_cache.ctx_ptr)
|
|
|
|
}
|
2019-02-14 23:13:58 +00:00
|
|
|
}
|