Skip to content

Commit

Permalink
Merge pull request #1870 from wasmerio/singlepass-addressmap
Browse files Browse the repository at this point in the history
Added basic AddressMap support for singlepass
  • Loading branch information
syrusakbary authored Dec 8, 2020
2 parents 346180e + f2356ed commit 9fc32df
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 21 deletions.
20 changes: 20 additions & 0 deletions lib/compiler-singlepass/src/address_map.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use wasmer_compiler::{FunctionAddressMap, FunctionBodyData, InstructionAddressMap, SourceLoc};

pub fn get_function_address_map<'data>(
instructions: Vec<InstructionAddressMap>,
data: &FunctionBodyData<'data>,
body_len: usize,
) -> FunctionAddressMap {
// Generate source loc for a function start/end to identify boundary within module.
// It will wrap around if byte code is larger than 4 GB.
let start_srcloc = SourceLoc::new(data.module_offset as u32);
let end_srcloc = SourceLoc::new((data.module_offset + data.data.len()) as u32);

FunctionAddressMap {
instructions,
start_srcloc,
end_srcloc,
body_offset: 0,
body_len,
}
}
103 changes: 83 additions & 20 deletions lib/compiler-singlepass/src/codegen_x64.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::address_map::get_function_address_map;
use crate::{common_decl::*, config::Singlepass, emitter_x64::*, machine::Machine, x64_decl::*};
use dynasmrt::{x64::Assembler, DynamicLabel};
use smallvec::{smallvec, SmallVec};
Expand All @@ -8,8 +9,8 @@ use wasmer_compiler::wasmparser::{
};
use wasmer_compiler::{
CompiledFunction, CompiledFunctionFrameInfo, CustomSection, CustomSectionProtection,
FunctionBody, Relocation, RelocationKind, RelocationTarget, SectionBody, SectionIndex,
TrapInformation,
FunctionBody, FunctionBodyData, InstructionAddressMap, Relocation, RelocationKind,
RelocationTarget, SectionBody, SectionIndex, SourceLoc, TrapInformation,
};
use wasmer_types::{
entity::{EntityRef, PrimaryMap, SecondaryMap},
Expand Down Expand Up @@ -80,6 +81,14 @@ pub struct FuncGen<'a> {

/// A set of special labels for trapping.
special_labels: SpecialLabelSet,

/// The source location for the current operator.
src_loc: u32,

/// Map from byte offset into wasm function to range of native instructions.
///
// Ordered by increasing InstructionAddressMap::srcloc.
instructions_address_map: Vec<InstructionAddressMap>,
}

struct SpecialLabelSet {
Expand Down Expand Up @@ -251,6 +260,11 @@ struct I2O1 {
}

impl<'a> FuncGen<'a> {
/// Set the source location of the Wasm to the given offset.
pub fn set_srcloc(&mut self, offset: u32) {
self.src_loc = offset;
}

fn get_location_released(&mut self, loc: Location) -> Location {
self.machine.release_locations(&mut self.assembler, &[loc]);
loc
Expand Down Expand Up @@ -306,13 +320,15 @@ impl<'a> FuncGen<'a> {
for i in begin..end {
self.trap_table.offset_to_code.insert(i, code);
}
self.mark_instruction_address_end(begin);
ret
}

/// Marks one address as trappable with trap code `code`.
fn mark_address_with_trap_code(&mut self, code: TrapCode) {
let offset = self.assembler.get_offset().0;
self.trap_table.offset_to_code.insert(offset, code);
self.mark_instruction_address_end(offset);
}

/// Canonicalizes the floating point value at `input` into `output`.
Expand Down Expand Up @@ -379,17 +395,21 @@ impl<'a> FuncGen<'a> {
Location::Imm64(_) | Location::Imm32(_) => {
self.assembler.emit_mov(sz, loc, Location::GPR(GPR::RCX)); // must not be used during div (rax, rdx)
self.mark_trappable();
let offset = self.assembler.get_offset().0;
self.trap_table
.offset_to_code
.insert(self.assembler.get_offset().0, TrapCode::IntegerOverflow);
.insert(offset, TrapCode::IntegerOverflow);
op(&mut self.assembler, sz, Location::GPR(GPR::RCX));
self.mark_instruction_address_end(offset);
}
_ => {
self.mark_trappable();
let offset = self.assembler.get_offset().0;
self.trap_table
.offset_to_code
.insert(self.assembler.get_offset().0, TrapCode::IntegerOverflow);
.insert(offset, TrapCode::IntegerOverflow);
op(&mut self.assembler, sz, loc);
self.mark_instruction_address_end(offset);
}
}
}
Expand Down Expand Up @@ -1473,17 +1493,21 @@ impl<'a> FuncGen<'a> {
);

self.assembler.emit_label(trap_overflow);
let offset = self.assembler.get_offset().0;
self.trap_table
.offset_to_code
.insert(self.assembler.get_offset().0, TrapCode::IntegerOverflow);
.insert(offset, TrapCode::IntegerOverflow);
self.assembler.emit_ud2();
self.mark_instruction_address_end(offset);

self.assembler.emit_label(trap_badconv);
self.trap_table.offset_to_code.insert(
self.assembler.get_offset().0,
TrapCode::BadConversionToInteger,
);

let offset = self.assembler.get_offset().0;
self.trap_table
.offset_to_code
.insert(offset, TrapCode::BadConversionToInteger);
self.assembler.emit_ud2();
self.mark_instruction_address_end(offset);

self.assembler.emit_label(end);
}
Expand Down Expand Up @@ -1622,17 +1646,20 @@ impl<'a> FuncGen<'a> {
);

self.assembler.emit_label(trap_overflow);
let offset = self.assembler.get_offset().0;
self.trap_table
.offset_to_code
.insert(self.assembler.get_offset().0, TrapCode::IntegerOverflow);
.insert(offset, TrapCode::IntegerOverflow);
self.assembler.emit_ud2();
self.mark_instruction_address_end(offset);

self.assembler.emit_label(trap_badconv);
self.trap_table.offset_to_code.insert(
self.assembler.get_offset().0,
TrapCode::BadConversionToInteger,
);
let offset = self.assembler.get_offset().0;
self.trap_table
.offset_to_code
.insert(offset, TrapCode::BadConversionToInteger);
self.assembler.emit_ud2();
self.mark_instruction_address_end(offset);

self.assembler.emit_label(end);
}
Expand Down Expand Up @@ -1754,6 +1781,14 @@ impl<'a> FuncGen<'a> {

// TODO: Full preemption by explicit signal checking

// We insert set StackOverflow as the default trap that can happen
// anywhere in the function prologue.
let offset = 0;
self.trap_table
.offset_to_code
.insert(offset, TrapCode::StackOverflow);
self.mark_instruction_address_end(offset);

if self.machine.state.wasm_inst_offset != std::usize::MAX {
return Err(CodegenError {
message: "emit_head: wasm_inst_offset not std::usize::MAX".to_string(),
Expand All @@ -1762,6 +1797,16 @@ impl<'a> FuncGen<'a> {
Ok(())
}

/// Pushes the instruction to the address map, calculating the offset from a
/// provided beginning address.
fn mark_instruction_address_end(&mut self, begin: usize) {
self.instructions_address_map.push(InstructionAddressMap {
srcloc: SourceLoc::new(self.src_loc),
code_offset: begin,
code_len: self.assembler.get_offset().0 - begin,
});
}

pub fn new(
module: &'a ModuleInfo,
config: &'a Singlepass,
Expand Down Expand Up @@ -1819,6 +1864,8 @@ impl<'a> FuncGen<'a> {
trap_table: TrapTable::default(),
relocations: vec![],
special_labels,
src_loc: 0,
instructions_address_map: vec![],
};
fg.emit_head()?;
Ok(fg)
Expand Down Expand Up @@ -5165,7 +5212,12 @@ impl<'a> FuncGen<'a> {

self.emit_call_sysv(
|this| {
let offset = this.assembler.get_offset().0;
this.trap_table
.offset_to_code
.insert(offset, TrapCode::StackOverflow);
this.assembler.emit_call_location(Location::GPR(GPR::RAX));
this.mark_instruction_address_end(offset);
},
params.iter().copied(),
)?;
Expand Down Expand Up @@ -5358,10 +5410,15 @@ impl<'a> FuncGen<'a> {
),
);
} else {
let offset = this.assembler.get_offset().0;
this.trap_table
.offset_to_code
.insert(offset, TrapCode::StackOverflow);
this.assembler.emit_call_location(Location::Memory(
GPR::RAX,
vmcaller_checked_anyfunc_func_ptr as i32,
));
this.mark_instruction_address_end(offset);
}
},
params.iter().copied(),
Expand Down Expand Up @@ -6128,11 +6185,12 @@ impl<'a> FuncGen<'a> {
}
Operator::Unreachable => {
self.mark_trappable();
self.trap_table.offset_to_code.insert(
self.assembler.get_offset().0,
TrapCode::UnreachableCodeReached,
);
let offset = self.assembler.get_offset().0;
self.trap_table
.offset_to_code
.insert(offset, TrapCode::UnreachableCodeReached);
self.assembler.emit_ud2();
self.mark_instruction_address_end(offset);
self.unreachable_depth = 1;
}
Operator::Return => {
Expand Down Expand Up @@ -8125,7 +8183,7 @@ impl<'a> FuncGen<'a> {
Ok(())
}

pub fn finalize(mut self) -> CompiledFunction {
pub fn finalize(mut self, data: &FunctionBodyData) -> CompiledFunction {
// Generate actual code for special labels.
self.assembler
.emit_label(self.special_labels.integer_division_by_zero);
Expand Down Expand Up @@ -8153,6 +8211,11 @@ impl<'a> FuncGen<'a> {

// Notify the assembler backend to generate necessary code at end of function.
self.assembler.finalize_function();

let body_len = self.assembler.get_offset().0;
let instructions_address_map = self.instructions_address_map;
let address_map = get_function_address_map(instructions_address_map, data, body_len);

CompiledFunction {
body: FunctionBody {
body: self.assembler.finalize().unwrap().to_vec(),
Expand All @@ -8170,7 +8233,7 @@ impl<'a> FuncGen<'a> {
trap_code: code,
})
.collect(),
..Default::default()
address_map,
},
}
}
Expand Down
3 changes: 2 additions & 1 deletion lib/compiler-singlepass/src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,12 @@ impl Compiler for SinglepassCompiler {
.map_err(to_compile_error)?;

while generator.has_control_frames() {
generator.set_srcloc(reader.original_position() as u32);
let op = reader.read_operator().map_err(to_compile_error)?;
generator.feed_operator(op).map_err(to_compile_error)?;
}

Ok(generator.finalize())
Ok(generator.finalize(&input))
})
.collect::<Result<Vec<CompiledFunction>, CompileError>>()?
.into_iter()
Expand Down
1 change: 1 addition & 0 deletions lib/compiler-singlepass/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
//! Compared to Cranelift and LLVM, Singlepass compiles much faster but has worse
//! runtime performance.
mod address_map;
mod codegen_x64;
mod common_decl;
mod compiler;
Expand Down
1 change: 1 addition & 0 deletions lib/engine/src/trap/frame_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ impl ModuleInfoFrameInfo {
}
}

#[derive(Debug)]
struct FunctionInfo {
start: usize,
local_index: LocalFunctionIndex,
Expand Down

0 comments on commit 9fc32df

Please sign in to comment.