mirror of
https://github.com/mii443/wasmer.git
synced 2025-08-24 17:29:26 +00:00
Implement all reference types instructions in compiler-llvm.
Remove spectest ignores for reference types tests on llvm. Extend llvm ABIs to pass externref and funcref. Expose all libcalls through the Libcalls enum. Add support for all libcalls to llvm object_file.rs, even libcalls that we aren't using. Add missing no_mangle to libcalls. Change 'memory' to 'memory32' in libcalls in preparation for the memory64 proposal. Remove 'local' from 'wasmer_local_memory_copy' in libcalls to fit naming convention. Add mangling of externref and funcref for llvm-debug-dir. Mark 'wasmer_func_ref' readonly.
This commit is contained in:
@ -9344,6 +9344,192 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> {
|
||||
size.add_attribute(AttributeLoc::Function, self.intrinsics.readonly);
|
||||
self.state.push1(size.try_as_basic_value().left().unwrap());
|
||||
}
|
||||
/***************************
|
||||
* Reference types.
|
||||
* https://github.com/WebAssembly/reference-types/blob/master/proposals/reference-types/Overview.md
|
||||
***************************/
|
||||
Operator::RefNull { .. } => {
|
||||
self.state.push1(self.intrinsics.funcref_ty.const_null());
|
||||
}
|
||||
Operator::RefIsNull => {
|
||||
let value = self.state.pop1()?.into_pointer_value();
|
||||
let is_null = self.builder.build_is_null(value, "");
|
||||
let is_null = self
|
||||
.builder
|
||||
.build_int_z_extend(is_null, self.intrinsics.i32_ty, "");
|
||||
self.state.push1(is_null);
|
||||
}
|
||||
Operator::RefFunc { function_index } => {
|
||||
let index = self
|
||||
.intrinsics
|
||||
.i32_ty
|
||||
.const_int(function_index.into(), false)
|
||||
.as_basic_value_enum();
|
||||
let value = self
|
||||
.builder
|
||||
.build_call(self.intrinsics.func_ref, &[self.ctx.basic(), index], "")
|
||||
.try_as_basic_value()
|
||||
.left()
|
||||
.unwrap();
|
||||
self.state.push1(value);
|
||||
}
|
||||
Operator::TableGet { table } => {
|
||||
let table_index = self
|
||||
.intrinsics
|
||||
.i32_ty
|
||||
.const_int(table.into(), false)
|
||||
.as_basic_value_enum();
|
||||
let elem = self.state.pop1()?;
|
||||
let table_get = if let Some(_) = self
|
||||
.wasm_module
|
||||
.local_table_index(TableIndex::from_u32(table))
|
||||
{
|
||||
self.intrinsics.table_get
|
||||
} else {
|
||||
self.intrinsics.imported_table_get
|
||||
};
|
||||
let value = self
|
||||
.builder
|
||||
.build_call(table_get, &[self.ctx.basic(), table_index, elem], "")
|
||||
.try_as_basic_value()
|
||||
.left()
|
||||
.unwrap();
|
||||
self.state.push1(value);
|
||||
}
|
||||
Operator::TableSet { table } => {
|
||||
let table_index = self
|
||||
.intrinsics
|
||||
.i32_ty
|
||||
.const_int(table.into(), false)
|
||||
.as_basic_value_enum();
|
||||
let (elem, value) = self.state.pop2()?;
|
||||
let table_set = if let Some(_) = self
|
||||
.wasm_module
|
||||
.local_table_index(TableIndex::from_u32(table))
|
||||
{
|
||||
self.intrinsics.table_set
|
||||
} else {
|
||||
self.intrinsics.imported_table_set
|
||||
};
|
||||
self.builder.build_call(
|
||||
table_set,
|
||||
&[self.ctx.basic(), table_index, elem, value],
|
||||
"",
|
||||
);
|
||||
}
|
||||
Operator::TableCopy {
|
||||
dst_table,
|
||||
src_table,
|
||||
} => {
|
||||
let (dst, src, len) = self.state.pop3()?;
|
||||
let dst_table = self
|
||||
.intrinsics
|
||||
.i32_ty
|
||||
.const_int(dst_table as u64, false)
|
||||
.as_basic_value_enum();
|
||||
let src_table = self
|
||||
.intrinsics
|
||||
.i32_ty
|
||||
.const_int(src_table as u64, false)
|
||||
.as_basic_value_enum();
|
||||
self.builder.build_call(
|
||||
self.intrinsics.table_copy,
|
||||
&[self.ctx.basic(), dst_table, src_table, dst, src, len],
|
||||
"",
|
||||
);
|
||||
}
|
||||
Operator::TableInit { segment, table } => {
|
||||
let (dst, src, len) = self.state.pop3()?;
|
||||
let segment = self
|
||||
.intrinsics
|
||||
.i32_ty
|
||||
.const_int(segment as u64, false)
|
||||
.as_basic_value_enum();
|
||||
let table = self
|
||||
.intrinsics
|
||||
.i32_ty
|
||||
.const_int(table as u64, false)
|
||||
.as_basic_value_enum();
|
||||
self.builder.build_call(
|
||||
self.intrinsics.table_init,
|
||||
&[self.ctx.basic(), table, segment, dst, src, len],
|
||||
"",
|
||||
);
|
||||
}
|
||||
Operator::ElemDrop { segment } => {
|
||||
let segment = self
|
||||
.intrinsics
|
||||
.i32_ty
|
||||
.const_int(segment as u64, false)
|
||||
.as_basic_value_enum();
|
||||
self.builder.build_call(
|
||||
self.intrinsics.elem_drop,
|
||||
&[self.ctx.basic(), segment],
|
||||
"",
|
||||
);
|
||||
}
|
||||
Operator::TableFill { table } => {
|
||||
let table = self
|
||||
.intrinsics
|
||||
.i32_ty
|
||||
.const_int(table as u64, false)
|
||||
.as_basic_value_enum();
|
||||
let (start, elem, len) = self.state.pop3()?;
|
||||
self.builder.build_call(
|
||||
self.intrinsics.table_fill,
|
||||
&[self.ctx.basic(), table, start, elem, len],
|
||||
"",
|
||||
);
|
||||
}
|
||||
Operator::TableGrow { table } => {
|
||||
let (elem, delta) = self.state.pop2()?;
|
||||
let (table_grow, table_index) = if let Some(local_table_index) = self
|
||||
.wasm_module
|
||||
.local_table_index(TableIndex::from_u32(table))
|
||||
{
|
||||
(self.intrinsics.table_grow, local_table_index.as_u32())
|
||||
} else {
|
||||
(self.intrinsics.imported_table_grow, table)
|
||||
};
|
||||
let table_index = self
|
||||
.intrinsics
|
||||
.i32_ty
|
||||
.const_int(table_index as u64, false)
|
||||
.as_basic_value_enum();
|
||||
let size = self
|
||||
.builder
|
||||
.build_call(
|
||||
table_grow,
|
||||
&[self.ctx.basic(), elem, delta, table_index],
|
||||
"",
|
||||
)
|
||||
.try_as_basic_value()
|
||||
.left()
|
||||
.unwrap();
|
||||
self.state.push1(size);
|
||||
}
|
||||
Operator::TableSize { table } => {
|
||||
let (table_size, table_index) = if let Some(local_table_index) = self
|
||||
.wasm_module
|
||||
.local_table_index(TableIndex::from_u32(table))
|
||||
{
|
||||
(self.intrinsics.table_size, local_table_index.as_u32())
|
||||
} else {
|
||||
(self.intrinsics.imported_table_size, table)
|
||||
};
|
||||
let table_index = self
|
||||
.intrinsics
|
||||
.i32_ty
|
||||
.const_int(table_index as u64, false)
|
||||
.as_basic_value_enum();
|
||||
let size = self
|
||||
.builder
|
||||
.build_call(table_size, &[self.ctx.basic(), table_index], "")
|
||||
.try_as_basic_value()
|
||||
.left()
|
||||
.unwrap();
|
||||
self.state.push1(size);
|
||||
}
|
||||
_ => {
|
||||
return Err(CompileError::Codegen(format!(
|
||||
"Operator {:?} unimplemented",
|
||||
|
Reference in New Issue
Block a user