Implement memory.grow and memory.current (#9)
* Implement. * Clean and doc * Collect base addresses instead of leaking them * Fix code for 1.25. * Simplify $assert * Use AbiParam::special. * Use &mut self in base_addr
This commit is contained in:
committed by
Dan Gohman
parent
5379605737
commit
e7c8d23a42
@@ -46,16 +46,19 @@ impl binemit::RelocSink for RelocSink {
|
||||
name: &ExternalName,
|
||||
addend: binemit::Addend,
|
||||
) {
|
||||
// FIXME: Handle grow_memory/current_memory.
|
||||
let func_index = if let ExternalName::User { namespace, index } = *name {
|
||||
let reloc_target = if let ExternalName::User { namespace, index } = *name {
|
||||
debug_assert!(namespace == 0);
|
||||
index
|
||||
RelocationTarget::UserFunc(index as usize)
|
||||
} else if *name == ExternalName::testcase("grow_memory") {
|
||||
RelocationTarget::GrowMemory
|
||||
} else if *name == ExternalName::testcase("current_memory") {
|
||||
RelocationTarget::CurrentMemory
|
||||
} else {
|
||||
panic!("unrecognized external name")
|
||||
} as usize;
|
||||
};
|
||||
self.func_relocs.push(Relocation {
|
||||
reloc,
|
||||
func_index,
|
||||
reloc_target,
|
||||
offset,
|
||||
addend,
|
||||
});
|
||||
@@ -83,14 +86,25 @@ impl RelocSink {
|
||||
pub struct Relocation {
|
||||
/// The relocation code.
|
||||
pub reloc: binemit::Reloc,
|
||||
/// The function index.
|
||||
pub func_index: FunctionIndex,
|
||||
/// Relocation target.
|
||||
pub reloc_target: RelocationTarget,
|
||||
/// The offset where to apply the relocation.
|
||||
pub offset: binemit::CodeOffset,
|
||||
/// The addend to add to the relocation value.
|
||||
pub addend: binemit::Addend,
|
||||
}
|
||||
|
||||
/// Destination function. Can be either user function or some special one, like grow_memory.
|
||||
#[derive(Debug)]
|
||||
pub enum RelocationTarget {
|
||||
/// The user function index.
|
||||
UserFunc(FunctionIndex),
|
||||
/// Function for growing the default memory by the specified amount of pages.
|
||||
GrowMemory,
|
||||
/// Function for query current size of the default linear memory.
|
||||
CurrentMemory,
|
||||
}
|
||||
|
||||
/// Relocations to apply to function bodies.
|
||||
pub type Relocations = Vec<Vec<Relocation>>;
|
||||
|
||||
|
||||
@@ -3,8 +3,7 @@ use cranelift_codegen::ir;
|
||||
use cranelift_codegen::ir::immediates::Offset32;
|
||||
use cranelift_codegen::ir::types::*;
|
||||
use cranelift_codegen::ir::{
|
||||
AbiParam, ArgumentExtension, ArgumentLoc, ArgumentPurpose, ExtFuncData, ExternalName, FuncRef,
|
||||
Function, InstBuilder, Signature,
|
||||
AbiParam, ArgumentPurpose, ExtFuncData, ExternalName, FuncRef, Function, InstBuilder, Signature,
|
||||
};
|
||||
use cranelift_codegen::isa;
|
||||
use cranelift_codegen::settings;
|
||||
@@ -132,12 +131,10 @@ impl<'data, 'module> cranelift_wasm::ModuleEnvironment<'data>
|
||||
|
||||
fn declare_signature(&mut self, sig: &ir::Signature) {
|
||||
let mut sig = sig.clone();
|
||||
sig.params.push(AbiParam {
|
||||
value_type: self.pointer_type(),
|
||||
purpose: ArgumentPurpose::VMContext,
|
||||
extension: ArgumentExtension::None,
|
||||
location: ArgumentLoc::Unassigned,
|
||||
});
|
||||
sig.params.push(AbiParam::special(
|
||||
self.pointer_type(),
|
||||
ArgumentPurpose::VMContext,
|
||||
));
|
||||
// TODO: Deduplicate signatures.
|
||||
self.module.signatures.push(sig);
|
||||
}
|
||||
@@ -377,7 +374,10 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
|
||||
let sig_ref = pos.func.import_signature(Signature {
|
||||
call_conv: self.isa.flags().call_conv(),
|
||||
argument_bytes: None,
|
||||
params: vec![AbiParam::new(I32)],
|
||||
params: vec![
|
||||
AbiParam::new(I32),
|
||||
AbiParam::special(self.pointer_type(), ArgumentPurpose::VMContext),
|
||||
],
|
||||
returns: vec![AbiParam::new(I32)],
|
||||
});
|
||||
// We currently allocate all code segments independently, so nothing
|
||||
@@ -391,7 +391,8 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
|
||||
})
|
||||
});
|
||||
self.grow_memory_extfunc = Some(grow_mem_func);
|
||||
let call_inst = pos.ins().call(grow_mem_func, &[val]);
|
||||
let vmctx = pos.func.special_param(ArgumentPurpose::VMContext).unwrap();
|
||||
let call_inst = pos.ins().call(grow_mem_func, &[val, vmctx]);
|
||||
Ok(*pos.func.dfg.inst_results(call_inst).first().unwrap())
|
||||
}
|
||||
|
||||
@@ -406,7 +407,10 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
|
||||
let sig_ref = pos.func.import_signature(Signature {
|
||||
call_conv: self.isa.flags().call_conv(),
|
||||
argument_bytes: None,
|
||||
params: Vec::new(),
|
||||
params: vec![AbiParam::special(
|
||||
self.pointer_type(),
|
||||
ArgumentPurpose::VMContext,
|
||||
)],
|
||||
returns: vec![AbiParam::new(I32)],
|
||||
});
|
||||
// We currently allocate all code segments independently, so nothing
|
||||
@@ -420,7 +424,8 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
|
||||
})
|
||||
});
|
||||
self.current_memory_extfunc = Some(cur_mem_func);
|
||||
let call_inst = pos.ins().call(cur_mem_func, &[]);
|
||||
let vmctx = pos.func.special_param(ArgumentPurpose::VMContext).unwrap();
|
||||
let call_inst = pos.ins().call(cur_mem_func, &[vmctx]);
|
||||
Ok(*pos.func.dfg.inst_results(call_inst).first().unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,6 @@ mod compilation;
|
||||
mod environ;
|
||||
mod module;
|
||||
|
||||
pub use compilation::{compile_module, Compilation, Relocation, Relocations};
|
||||
pub use compilation::{compile_module, Compilation, Relocation, RelocationTarget, Relocations};
|
||||
pub use environ::{ModuleEnvironment, ModuleTranslation};
|
||||
pub use module::{DataInitializer, Module, TableElements};
|
||||
|
||||
Reference in New Issue
Block a user