mirror of
https://github.com/fluencelabs/wasmer
synced 2025-07-31 15:22:03 +00:00
Trying to upgrade Cranelift to 0.23
This commit is contained in:
@@ -4,7 +4,6 @@
|
||||
use std::collections::HashMap;
|
||||
use std::string::String;
|
||||
use std::vec::Vec;
|
||||
use target_lexicon::{PointerWidth, Triple};
|
||||
|
||||
use cranelift_codegen::cursor::FuncCursor;
|
||||
use cranelift_codegen::ir::immediates::{Imm64, Offset32};
|
||||
@@ -12,13 +11,12 @@ use cranelift_codegen::ir::types::*;
|
||||
use cranelift_codegen::ir::{
|
||||
self, AbiParam, ArgumentPurpose, ExtFuncData, ExternalName, FuncRef, InstBuilder, Signature,
|
||||
};
|
||||
use cranelift_codegen::print_errors::pretty_verifier_error;
|
||||
use cranelift_codegen::settings::CallConv;
|
||||
use cranelift_codegen::{isa, settings, verifier};
|
||||
use cranelift_codegen::isa::{CallConv, TargetFrontendConfig};
|
||||
use cranelift_entity::{EntityRef, PrimaryMap};
|
||||
|
||||
use cranelift_wasm::{
|
||||
translate_module, // ReturnMode,
|
||||
translate_module,
|
||||
ReturnMode,
|
||||
DefinedFuncIndex,
|
||||
FuncEnvironment as FuncEnvironmentTrait,
|
||||
FuncIndex,
|
||||
@@ -78,11 +76,8 @@ pub enum Export {
|
||||
/// `Module` to allow it to be borrowed separately from the
|
||||
/// `FuncTranslator` field.
|
||||
pub struct ModuleInfo {
|
||||
/// Target description.
|
||||
pub triple: Triple,
|
||||
|
||||
/// Compilation setting flags.
|
||||
pub flags: settings::Flags,
|
||||
/// Target description relevant to frontends producing Cranelift IR.
|
||||
config: TargetFrontendConfig,
|
||||
|
||||
pub main_memory_base: Option<ir::GlobalValue>,
|
||||
|
||||
@@ -138,10 +133,9 @@ pub struct ModuleInfo {
|
||||
|
||||
impl ModuleInfo {
|
||||
/// Allocates the data structures with the given flags.
|
||||
pub fn with_triple_flags(triple: Triple, flags: settings::Flags) -> Self {
|
||||
pub fn new(config: TargetFrontendConfig) -> Self {
|
||||
Self {
|
||||
triple,
|
||||
flags,
|
||||
config,
|
||||
signatures: Vec::new(),
|
||||
imported_funcs: Vec::new(),
|
||||
functions: PrimaryMap::new(),
|
||||
@@ -214,17 +208,42 @@ pub struct Module {
|
||||
// return_mode: ReturnMode,
|
||||
}
|
||||
|
||||
fn native_pointer_type() -> ir::Type {
|
||||
if cfg!(target_pointer_width = "64") {
|
||||
ir::types::I64
|
||||
} else {
|
||||
ir::types::I32
|
||||
}
|
||||
}
|
||||
|
||||
/// Number of bytes in a native pointer.
|
||||
pub fn native_pointer_size() -> i32 {
|
||||
if cfg!(target_pointer_width = "64") {
|
||||
8
|
||||
} else {
|
||||
4
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn offset32(offset: usize) -> Offset32 {
|
||||
assert!(offset <= i32::max_value() as usize);
|
||||
(offset as i32).into()
|
||||
}
|
||||
/// Convert a usize offset into a `Imm64` for an iadd_imm.
|
||||
fn imm64(offset: usize) -> Imm64 {
|
||||
(offset as i64).into()
|
||||
}
|
||||
|
||||
impl Module {
|
||||
/// Instantiate a Module given WASM bytecode
|
||||
pub fn from_bytes(
|
||||
buffer_source: Vec<u8>,
|
||||
triple: Triple,
|
||||
flags: Option<settings::Flags>,
|
||||
config: TargetFrontendConfig,
|
||||
) -> Result<Self, ErrorKind> {
|
||||
// let return_mode = ReturnMode::NormalReturns;
|
||||
let flags = flags.unwrap_or_else(|| settings::Flags::new(settings::builder()));
|
||||
let mut module = Self {
|
||||
info: ModuleInfo::with_triple_flags(triple, flags),
|
||||
info: ModuleInfo::new(config),
|
||||
trans: FuncTranslator::new(),
|
||||
func_bytecode_sizes: Vec::new(),
|
||||
// return_mode,
|
||||
@@ -265,15 +284,16 @@ impl Module {
|
||||
}
|
||||
|
||||
pub fn verify(&self) {
|
||||
let isa = isa::lookup(self.info.triple.clone())
|
||||
.unwrap()
|
||||
.finish(self.info.flags.clone());
|
||||
unimplemented!();
|
||||
// let isa = isa::lookup(self.info.triple.clone())
|
||||
// .unwrap()
|
||||
// .finish(self.info.flags.clone());
|
||||
|
||||
for func in self.info.function_bodies.values() {
|
||||
verifier::verify_function(func, &*isa)
|
||||
.map_err(|errors| panic!(pretty_verifier_error(func, Some(&*isa), None, errors)))
|
||||
.unwrap();
|
||||
}
|
||||
// for func in self.info.function_bodies.values() {
|
||||
// verifier::verify_function(func, &*isa)
|
||||
// .map_err(|errors| panic!(pretty_verifier_error(func, Some(&*isa), None, errors)))
|
||||
// .unwrap();
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -302,96 +322,104 @@ impl<'environment> FuncEnvironment<'environment> {
|
||||
// Create a signature for `sigidx` amended with a `vmctx` argument after the standard wasm
|
||||
// arguments.
|
||||
fn vmctx_sig(&self, sigidx: SignatureIndex) -> ir::Signature {
|
||||
let mut sig = self.mod_info.signatures[sigidx].clone();
|
||||
let mut sig = self.mod_info.signatures[sigidx.index()].clone();
|
||||
sig.params.push(ir::AbiParam::special(
|
||||
self.pointer_type(),
|
||||
ir::ArgumentPurpose::VMContext,
|
||||
));
|
||||
sig
|
||||
}
|
||||
|
||||
fn ptr_size(&self) -> usize {
|
||||
if self.triple().pointer_width().unwrap() == PointerWidth::U64 {
|
||||
8
|
||||
} else {
|
||||
4
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'environment> FuncEnvironmentTrait for FuncEnvironment<'environment> {
|
||||
fn triple(&self) -> &Triple {
|
||||
&self.mod_info.triple
|
||||
/// Get the information needed to produce Cranelift IR for the given target.
|
||||
fn target_config(&self) -> TargetFrontendConfig {
|
||||
self.mod_info.config
|
||||
}
|
||||
|
||||
fn flags(&self) -> &settings::Flags {
|
||||
&self.mod_info.flags
|
||||
/// Get the Cranelift integer type to use for native pointers.
|
||||
///
|
||||
/// This returns `I64` for 64-bit architectures and `I32` for 32-bit architectures.
|
||||
fn pointer_type(&self) -> ir::Type {
|
||||
ir::Type::int(u16::from(self.target_config().pointer_bits())).unwrap()
|
||||
}
|
||||
|
||||
/// Get the size of a native pointer, in bytes.
|
||||
fn pointer_bytes(&self) -> u8 {
|
||||
self.target_config().pointer_bytes()
|
||||
}
|
||||
|
||||
fn make_table(&mut self, func: &mut ir::Function, table_index: TableIndex) -> ir::Table {
|
||||
assert_eq!(table_index.index(), 0, "Only one WebAssembly memory supported");
|
||||
let vmctx = func.create_global_value(ir::GlobalValueData::VMContext);
|
||||
let ptr_size = self.ptr_size();
|
||||
let ptr_size = native_pointer_size();
|
||||
|
||||
// Given a instance, we want to retrieve instance.tables
|
||||
// Create a table whose base address is stored at `instance+0`.
|
||||
// 0 is the offset of the vmctx.tables pointer respect to vmctx pointer
|
||||
let base = func.create_global_value(ir::GlobalValueData::Load {
|
||||
base: vmctx,
|
||||
offset: Offset32::new(0),
|
||||
offset: offset32(0),
|
||||
global_type: self.pointer_type(),
|
||||
readonly: true,
|
||||
});
|
||||
|
||||
// This will be 0 when the index is 0, not sure if the offset will work regardless
|
||||
let table_data_offset = (table_index as usize * ptr_size * 2) as i32;
|
||||
// let table_data_offset = table_index.index() * (ptr_size as usize) * 2 + ptr_size;
|
||||
|
||||
// We get the pointer for our table index
|
||||
let base_gv = func.create_global_value(ir::GlobalValueData::Load {
|
||||
base: base,
|
||||
offset: Offset32::new(table_data_offset),
|
||||
global_type: self.pointer_type(),
|
||||
});
|
||||
|
||||
let bound_gv = func.create_global_value(ir::GlobalValueData::Load {
|
||||
base: base,
|
||||
offset: Offset32::new(table_data_offset),
|
||||
offset: offset32(0),
|
||||
global_type: I64,
|
||||
readonly: false,
|
||||
});
|
||||
|
||||
let base_gv = func.create_global_value(ir::GlobalValueData::Load {
|
||||
base: base,
|
||||
offset: offset32(ptr_size as usize),
|
||||
global_type: self.pointer_type(),
|
||||
readonly: false
|
||||
});
|
||||
|
||||
let table = func.create_table(ir::TableData {
|
||||
base_gv: base_gv,
|
||||
min_size: Imm64::new(0),
|
||||
bound_gv,
|
||||
element_size: Imm64::new(i64::from(self.pointer_bytes())),
|
||||
index_type: self.pointer_type(),
|
||||
element_size: Imm64::new(i64::from(self.pointer_bytes()) * 2),
|
||||
index_type: I64,
|
||||
});
|
||||
// println!("FUNC {:?}", func);
|
||||
table
|
||||
}
|
||||
|
||||
fn make_heap(&mut self, func: &mut ir::Function, index: MemoryIndex) -> ir::Heap {
|
||||
fn make_heap(&mut self, func: &mut ir::Function, memory_index: MemoryIndex) -> ir::Heap {
|
||||
// Create a static heap whose base address is stored at `instance+8`.
|
||||
let vmctx = func.create_global_value(ir::GlobalValueData::VMContext);
|
||||
|
||||
let heap_base_addr = func.create_global_value(ir::GlobalValueData::Load {
|
||||
base: vmctx,
|
||||
offset: Offset32::new(8),
|
||||
offset: offset32(8),
|
||||
global_type: self.pointer_type(),
|
||||
readonly: true,
|
||||
});
|
||||
|
||||
let pointer_bytes = self.pointer_bytes();
|
||||
let memories_offset = (index * pointer_bytes as usize) as i32;
|
||||
let pointer_bytes = self.pointer_bytes() as usize;
|
||||
let memories_offset = memory_index.index() * pointer_bytes;
|
||||
|
||||
// We de-reference the vm_context.memories addr
|
||||
let heap_base = func.create_global_value(ir::GlobalValueData::Load {
|
||||
base: heap_base_addr,
|
||||
offset: Offset32::new(memories_offset),
|
||||
offset: offset32(memories_offset),
|
||||
global_type: self.pointer_type(),
|
||||
readonly: true,
|
||||
});
|
||||
|
||||
let bound_gv = func.create_global_value(ir::GlobalValueData::Load {
|
||||
base: vmctx,
|
||||
offset: Offset32::new(120),
|
||||
offset: offset32(120),
|
||||
global_type: I32,
|
||||
readonly: false,
|
||||
});
|
||||
|
||||
func.create_heap(ir::HeapData {
|
||||
@@ -448,17 +476,18 @@ impl<'environment> FuncEnvironmentTrait for FuncEnvironment<'environment> {
|
||||
// }
|
||||
}
|
||||
|
||||
fn make_global(&mut self, func: &mut ir::Function, index: GlobalIndex) -> GlobalVariable {
|
||||
fn make_global(&mut self, func: &mut ir::Function, global_index: GlobalIndex) -> GlobalVariable {
|
||||
// Just create a dummy `vmctx` global.
|
||||
let vmctx = func.create_global_value(ir::GlobalValueData::VMContext);
|
||||
|
||||
let globals_base_addr = func.create_global_value(ir::GlobalValueData::Load {
|
||||
base: vmctx,
|
||||
offset: Offset32::new(16),
|
||||
offset: offset32(16),
|
||||
global_type: self.pointer_type(),
|
||||
readonly: false,
|
||||
});
|
||||
|
||||
let offset = (index * 8) as i64;
|
||||
let offset = (global_index.index() * 8) as i64;
|
||||
let iadd = func.create_global_value(ir::GlobalValueData::IAddImm {
|
||||
base: globals_base_addr,
|
||||
offset: Imm64::new(offset),
|
||||
@@ -466,7 +495,7 @@ impl<'environment> FuncEnvironmentTrait for FuncEnvironment<'environment> {
|
||||
});
|
||||
GlobalVariable::Memory {
|
||||
gv: iadd,
|
||||
ty: self.mod_info.globals[index].entity.ty,
|
||||
ty: self.mod_info.globals[global_index.index()].entity.ty,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -572,11 +601,11 @@ impl<'environment> FuncEnvironmentTrait for FuncEnvironment<'environment> {
|
||||
fn translate_memory_grow(
|
||||
&mut self,
|
||||
mut pos: FuncCursor,
|
||||
index: MemoryIndex,
|
||||
memory_index: MemoryIndex,
|
||||
_heap: ir::Heap,
|
||||
val: ir::Value,
|
||||
) -> WasmResult<ir::Value> {
|
||||
debug_assert_eq!(index, 0, "non-default memories not supported yet");
|
||||
debug_assert_eq!(memory_index.index(), 0, "non-default memories not supported yet");
|
||||
let grow_mem_func = self.mod_info.grow_memory_extfunc.unwrap_or_else(|| {
|
||||
let sig_ref = pos.func.import_signature(Signature {
|
||||
call_conv: CallConv::SystemV,
|
||||
@@ -600,20 +629,20 @@ impl<'environment> FuncEnvironmentTrait for FuncEnvironment<'environment> {
|
||||
});
|
||||
|
||||
// self.mod_info.grow_memory_extfunc = Some(grow_mem_func);
|
||||
let memory_index = pos.ins().iconst(I32, index as i64);
|
||||
let memory_index_value = pos.ins().iconst(I32, imm64(memory_index.index()));
|
||||
let vmctx = pos.func.special_param(ArgumentPurpose::VMContext).unwrap();
|
||||
|
||||
let call_inst = pos.ins().call(grow_mem_func, &[val, memory_index, vmctx]);
|
||||
let call_inst = pos.ins().call(grow_mem_func, &[val, memory_index_value, vmctx]);
|
||||
Ok(*pos.func.dfg.inst_results(call_inst).first().unwrap())
|
||||
}
|
||||
|
||||
fn translate_memory_size(
|
||||
&mut self,
|
||||
mut pos: FuncCursor,
|
||||
index: MemoryIndex,
|
||||
memory_index: MemoryIndex,
|
||||
_heap: ir::Heap,
|
||||
) -> WasmResult<ir::Value> {
|
||||
debug_assert_eq!(index, 0, "non-default memories not supported yet");
|
||||
debug_assert_eq!(memory_index.index(), 0, "non-default memories not supported yet");
|
||||
let cur_mem_func = self.mod_info.current_memory_extfunc.unwrap_or_else(|| {
|
||||
let sig_ref = pos.func.import_signature(Signature {
|
||||
call_conv: CallConv::SystemV,
|
||||
@@ -637,22 +666,22 @@ impl<'environment> FuncEnvironmentTrait for FuncEnvironment<'environment> {
|
||||
|
||||
// self.mod_info.current_memory_extfunc = cur_mem_func;
|
||||
|
||||
let memory_index = pos.ins().iconst(I32, index as i64);
|
||||
let memory_index_value = pos.ins().iconst(I32, imm64(memory_index.index()));
|
||||
let vmctx = pos.func.special_param(ArgumentPurpose::VMContext).unwrap();
|
||||
|
||||
let call_inst = pos.ins().call(cur_mem_func, &[memory_index, vmctx]);
|
||||
let call_inst = pos.ins().call(cur_mem_func, &[memory_index_value, vmctx]);
|
||||
Ok(*pos.func.dfg.inst_results(call_inst).first().unwrap())
|
||||
// Ok(pos.ins().iconst(I32, -1))
|
||||
}
|
||||
|
||||
// fn return_mode(&self) -> ReturnMode {
|
||||
// self.return_mode
|
||||
// }
|
||||
fn return_mode(&self) -> ReturnMode {
|
||||
ReturnMode::FallthroughReturn
|
||||
}
|
||||
}
|
||||
|
||||
impl<'data> ModuleEnvironment<'data> for Module {
|
||||
fn flags(&self) -> &settings::Flags {
|
||||
&self.info.flags
|
||||
fn target_config(&self) -> &TargetFrontendConfig {
|
||||
&self.info.config
|
||||
}
|
||||
|
||||
fn get_func_name(&self, func_index: FuncIndex) -> ir::ExternalName {
|
||||
@@ -676,7 +705,7 @@ impl<'data> ModuleEnvironment<'data> for Module {
|
||||
}
|
||||
|
||||
fn get_signature(&self, sig_index: SignatureIndex) -> &ir::Signature {
|
||||
&self.info.signatures[sig_index]
|
||||
&self.info.signatures[sig_index.index()]
|
||||
}
|
||||
|
||||
fn declare_func_import(
|
||||
@@ -713,7 +742,7 @@ impl<'data> ModuleEnvironment<'data> for Module {
|
||||
}
|
||||
|
||||
fn get_global(&self, global_index: GlobalIndex) -> &Global {
|
||||
&self.info.globals[global_index].entity
|
||||
&self.info.globals[global_index.index()].entity
|
||||
}
|
||||
|
||||
fn declare_table(&mut self, table: Table) {
|
||||
@@ -728,7 +757,7 @@ impl<'data> ModuleEnvironment<'data> for Module {
|
||||
elements: Vec<FuncIndex>,
|
||||
) {
|
||||
// NEW
|
||||
debug_assert!(base.is_none(), "global-value offsets not supported yet");
|
||||
// debug_assert!(base.is_none(), "global-value offsets not supported yet");
|
||||
self.info.table_elements.push(TableElements {
|
||||
table_index,
|
||||
base,
|
||||
@@ -767,7 +796,7 @@ impl<'data> ModuleEnvironment<'data> for Module {
|
||||
}
|
||||
|
||||
fn declare_table_export(&mut self, table_index: TableIndex, name: &'data str) {
|
||||
self.info.tables[table_index]
|
||||
self.info.tables[table_index.index()]
|
||||
.export_names
|
||||
.push(String::from(name));
|
||||
// We add to the exports to have O(1) retrieval
|
||||
@@ -777,7 +806,7 @@ impl<'data> ModuleEnvironment<'data> for Module {
|
||||
}
|
||||
|
||||
fn declare_memory_export(&mut self, memory_index: MemoryIndex, name: &'data str) {
|
||||
self.info.memories[memory_index]
|
||||
self.info.memories[memory_index.index()]
|
||||
.export_names
|
||||
.push(String::from(name));
|
||||
// We add to the exports to have O(1) retrieval
|
||||
@@ -787,7 +816,7 @@ impl<'data> ModuleEnvironment<'data> for Module {
|
||||
}
|
||||
|
||||
fn declare_global_export(&mut self, global_index: GlobalIndex, name: &'data str) {
|
||||
self.info.globals[global_index]
|
||||
self.info.globals[global_index.index()]
|
||||
.export_names
|
||||
.push(String::from(name));
|
||||
// We add to the exports to have O(1) retrieval
|
||||
|
Reference in New Issue
Block a user