Transform ranges and simple expressions (#63)
This commit is contained in:
committed by
Dan Gohman
parent
36b4ff8031
commit
4f04d7d873
@@ -27,6 +27,12 @@ pub struct FunctionAddressMap {
|
||||
/// The array is sorted by the InstructionAddressMap::code_offset field.
|
||||
pub instructions: Vec<InstructionAddressMap>,
|
||||
|
||||
/// Function start source location (normally declaration).
|
||||
pub start_srcloc: ir::SourceLoc,
|
||||
|
||||
/// Function end source location.
|
||||
pub end_srcloc: ir::SourceLoc,
|
||||
|
||||
/// Generated function body offset if applicable, otherwise 0.
|
||||
pub body_offset: usize,
|
||||
|
||||
@@ -36,3 +42,18 @@ pub struct FunctionAddressMap {
|
||||
|
||||
/// Module functions addresses mappings.
|
||||
pub type ModuleAddressMap = PrimaryMap<DefinedFuncIndex, FunctionAddressMap>;
|
||||
|
||||
/// Value ranges for functions.
|
||||
pub type ValueLabelsRanges = PrimaryMap<DefinedFuncIndex, cranelift_codegen::ValueLabelsRanges>;
|
||||
|
||||
/// Stack slots for functions.
|
||||
pub type StackSlots = PrimaryMap<DefinedFuncIndex, ir::StackSlots>;
|
||||
|
||||
/// Module `vmctx` related info.
|
||||
pub struct ModuleVmctxInfo {
|
||||
/// The memory definition offset in the VMContext structure.
|
||||
pub memory_offset: i64,
|
||||
|
||||
/// The functions stack slots.
|
||||
pub stack_slots: StackSlots,
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::address_map::ModuleAddressMap;
|
||||
use crate::address_map::{ModuleAddressMap, ValueLabelsRanges};
|
||||
use crate::compilation::{CodeAndJTOffsets, Compilation, Relocations};
|
||||
use crate::module::Module;
|
||||
use crate::module_environ::FunctionBodyData;
|
||||
@@ -102,9 +102,17 @@ pub struct ModuleCacheData {
|
||||
compilation: Compilation,
|
||||
relocations: Relocations,
|
||||
address_transforms: ModuleAddressMap,
|
||||
value_ranges: ValueLabelsRanges,
|
||||
stack_slots: PrimaryMap<DefinedFuncIndex, ir::StackSlots>,
|
||||
}
|
||||
|
||||
type ModuleCacheDataTupleType = (Compilation, Relocations, ModuleAddressMap);
|
||||
type ModuleCacheDataTupleType = (
|
||||
Compilation,
|
||||
Relocations,
|
||||
ModuleAddressMap,
|
||||
ValueLabelsRanges,
|
||||
PrimaryMap<DefinedFuncIndex, ir::StackSlots>,
|
||||
);
|
||||
|
||||
struct Sha256Hasher(Sha256);
|
||||
|
||||
@@ -225,11 +233,19 @@ impl ModuleCacheData {
|
||||
compilation: data.0,
|
||||
relocations: data.1,
|
||||
address_transforms: data.2,
|
||||
value_ranges: data.3,
|
||||
stack_slots: data.4,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_tuple(self) -> ModuleCacheDataTupleType {
|
||||
(self.compilation, self.relocations, self.address_transforms)
|
||||
(
|
||||
self.compilation,
|
||||
self.relocations,
|
||||
self.address_transforms,
|
||||
self.value_ranges,
|
||||
self.stack_slots,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//! A `Compilation` contains the compiled function bodies for a WebAssembly
|
||||
//! module.
|
||||
|
||||
use crate::address_map::ModuleAddressMap;
|
||||
use crate::address_map::{ModuleAddressMap, ValueLabelsRanges};
|
||||
use crate::module;
|
||||
use crate::module_environ::FunctionBodyData;
|
||||
use cranelift_codegen::{binemit, ir, isa, CodegenError};
|
||||
@@ -149,5 +149,14 @@ pub trait Compiler {
|
||||
function_body_inputs: PrimaryMap<DefinedFuncIndex, FunctionBodyData<'data>>,
|
||||
isa: &dyn isa::TargetIsa,
|
||||
generate_debug_info: bool,
|
||||
) -> Result<(Compilation, Relocations, ModuleAddressMap), CompileError>;
|
||||
) -> Result<
|
||||
(
|
||||
Compilation,
|
||||
Relocations,
|
||||
ModuleAddressMap,
|
||||
ValueLabelsRanges,
|
||||
PrimaryMap<DefinedFuncIndex, ir::StackSlots>,
|
||||
),
|
||||
CompileError,
|
||||
>;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
//! Support for compiling with Cranelift.
|
||||
|
||||
use crate::address_map::{FunctionAddressMap, InstructionAddressMap, ModuleAddressMap};
|
||||
use crate::address_map::{
|
||||
FunctionAddressMap, InstructionAddressMap, ModuleAddressMap, ValueLabelsRanges,
|
||||
};
|
||||
use crate::cache::{ModuleCacheData, ModuleCacheEntry};
|
||||
use crate::compilation::{
|
||||
CodeAndJTOffsets, Compilation, CompileError, Relocation, RelocationTarget, Relocations,
|
||||
@@ -90,8 +92,13 @@ impl RelocSink {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_address_transform(context: &Context, isa: &isa::TargetIsa) -> Vec<InstructionAddressMap> {
|
||||
let mut result = Vec::new();
|
||||
fn get_function_address_map<'data>(
|
||||
context: &Context,
|
||||
data: &FunctionBodyData<'data>,
|
||||
body_len: usize,
|
||||
isa: &isa::TargetIsa,
|
||||
) -> FunctionAddressMap {
|
||||
let mut instructions = Vec::new();
|
||||
|
||||
let func = &context.func;
|
||||
let mut ebbs = func.layout.ebbs().collect::<Vec<_>>();
|
||||
@@ -101,14 +108,27 @@ fn get_address_transform(context: &Context, isa: &isa::TargetIsa) -> Vec<Instruc
|
||||
for ebb in ebbs {
|
||||
for (offset, inst, size) in func.inst_offsets(ebb, &encinfo) {
|
||||
let srcloc = func.srclocs[inst];
|
||||
result.push(InstructionAddressMap {
|
||||
instructions.push(InstructionAddressMap {
|
||||
srcloc,
|
||||
code_offset: offset as usize,
|
||||
code_len: size as usize,
|
||||
});
|
||||
}
|
||||
}
|
||||
result
|
||||
|
||||
// Generate artificial srcloc for function start/end to identify boundary
|
||||
// within module. Similar to FuncTranslator::cur_srcloc(): it will wrap around
|
||||
// if byte code is larger than 4 GB.
|
||||
let start_srcloc = ir::SourceLoc::new(data.module_offset as u32);
|
||||
let end_srcloc = ir::SourceLoc::new((data.module_offset + data.data.len()) as u32);
|
||||
|
||||
FunctionAddressMap {
|
||||
instructions,
|
||||
start_srcloc,
|
||||
end_srcloc,
|
||||
body_offset: 0,
|
||||
body_len,
|
||||
}
|
||||
}
|
||||
|
||||
/// A compiler that compiles a WebAssembly module with Cranelift, translating the Wasm to Cranelift IR,
|
||||
@@ -123,7 +143,16 @@ impl crate::compilation::Compiler for Cranelift {
|
||||
function_body_inputs: PrimaryMap<DefinedFuncIndex, FunctionBodyData<'data>>,
|
||||
isa: &dyn isa::TargetIsa,
|
||||
generate_debug_info: bool,
|
||||
) -> Result<(Compilation, Relocations, ModuleAddressMap), CompileError> {
|
||||
) -> Result<
|
||||
(
|
||||
Compilation,
|
||||
Relocations,
|
||||
ModuleAddressMap,
|
||||
ValueLabelsRanges,
|
||||
PrimaryMap<DefinedFuncIndex, ir::StackSlots>,
|
||||
),
|
||||
CompileError,
|
||||
> {
|
||||
let cache_entry = ModuleCacheEntry::new(
|
||||
module,
|
||||
&function_body_inputs,
|
||||
@@ -138,6 +167,8 @@ impl crate::compilation::Compiler for Cranelift {
|
||||
let mut functions = PrimaryMap::with_capacity(function_body_inputs.len());
|
||||
let mut relocations = PrimaryMap::with_capacity(function_body_inputs.len());
|
||||
let mut address_transforms = PrimaryMap::with_capacity(function_body_inputs.len());
|
||||
let mut value_ranges = PrimaryMap::with_capacity(function_body_inputs.len());
|
||||
let mut stack_slots = PrimaryMap::with_capacity(function_body_inputs.len());
|
||||
|
||||
function_body_inputs
|
||||
.into_iter()
|
||||
@@ -149,6 +180,9 @@ impl crate::compilation::Compiler for Cranelift {
|
||||
context.func.name = get_func_name(func_index);
|
||||
context.func.signature =
|
||||
module.signatures[module.functions[func_index]].clone();
|
||||
if generate_debug_info {
|
||||
context.func.collect_debug_info();
|
||||
}
|
||||
|
||||
let mut trans = FuncTranslator::new();
|
||||
trans
|
||||
@@ -171,36 +205,48 @@ impl crate::compilation::Compiler for Cranelift {
|
||||
|
||||
let address_transform = if generate_debug_info {
|
||||
let body_len = code_buf.len();
|
||||
let at = get_address_transform(&context, isa);
|
||||
|
||||
Some(FunctionAddressMap {
|
||||
instructions: at,
|
||||
body_offset: 0,
|
||||
body_len,
|
||||
})
|
||||
Some(get_function_address_map(&context, input, body_len, isa))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let ranges = if generate_debug_info {
|
||||
Some(
|
||||
context
|
||||
.build_value_labels_ranges(isa)
|
||||
.map_err(CompileError::Codegen)?,
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let stack_slots = context.func.stack_slots.clone();
|
||||
|
||||
Ok((
|
||||
code_buf,
|
||||
jt_offsets,
|
||||
reloc_sink.func_relocs,
|
||||
address_transform,
|
||||
ranges,
|
||||
stack_slots,
|
||||
))
|
||||
})
|
||||
.collect::<Result<Vec<_>, CompileError>>()?
|
||||
.into_iter()
|
||||
.for_each(|(function, func_jt_offsets, relocs, address_transform)| {
|
||||
functions.push(CodeAndJTOffsets {
|
||||
body: function,
|
||||
jt_offsets: func_jt_offsets,
|
||||
});
|
||||
relocations.push(relocs);
|
||||
if let Some(address_transform) = address_transform {
|
||||
address_transforms.push(address_transform);
|
||||
}
|
||||
});
|
||||
.for_each(
|
||||
|(function, func_jt_offsets, relocs, address_transform, ranges, sss)| {
|
||||
functions.push(CodeAndJTOffsets {
|
||||
body: function,
|
||||
jt_offsets: func_jt_offsets,
|
||||
});
|
||||
relocations.push(relocs);
|
||||
if let Some(address_transform) = address_transform {
|
||||
address_transforms.push(address_transform);
|
||||
}
|
||||
value_ranges.push(ranges.unwrap_or(std::collections::HashMap::new()));
|
||||
stack_slots.push(sss);
|
||||
},
|
||||
);
|
||||
|
||||
// TODO: Reorganize where we create the Vec for the resolved imports.
|
||||
|
||||
@@ -208,6 +254,8 @@ impl crate::compilation::Compiler for Cranelift {
|
||||
Compilation::new(functions),
|
||||
relocations,
|
||||
address_transforms,
|
||||
value_ranges,
|
||||
stack_slots,
|
||||
));
|
||||
cache_entry.update_data(&data);
|
||||
data
|
||||
|
||||
@@ -51,7 +51,9 @@ pub mod cranelift;
|
||||
#[cfg(feature = "lightbeam")]
|
||||
pub mod lightbeam;
|
||||
|
||||
pub use crate::address_map::{FunctionAddressMap, InstructionAddressMap, ModuleAddressMap};
|
||||
pub use crate::address_map::{
|
||||
FunctionAddressMap, InstructionAddressMap, ModuleAddressMap, ModuleVmctxInfo, ValueLabelsRanges,
|
||||
};
|
||||
pub use crate::cache::conf as cache_conf;
|
||||
pub use crate::compilation::{
|
||||
Compilation, CompileError, Compiler, Relocation, RelocationTarget, Relocations,
|
||||
|
||||
Reference in New Issue
Block a user