Added address map instructions for traps in singlepass

This commit is contained in:
Syrus
2020-12-03 21:17:46 -08:00
parent ef48720268
commit 77458752f5
4 changed files with 115 additions and 21 deletions

View File

@ -0,0 +1,23 @@
// This file contains code from external sources.
// Attributions: https://github.com/wasmerio/wasmer/blob/master/ATTRIBUTIONS.md
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 artificial srcloc for 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,
}
}

View File

@ -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 crate::{common_decl::*, config::Singlepass, emitter_x64::*, machine::Machine, x64_decl::*};
use dynasmrt::{x64::Assembler, DynamicLabel}; use dynasmrt::{x64::Assembler, DynamicLabel};
use smallvec::{smallvec, SmallVec}; use smallvec::{smallvec, SmallVec};
@ -8,8 +9,8 @@ use wasmer_compiler::wasmparser::{
}; };
use wasmer_compiler::{ use wasmer_compiler::{
CompiledFunction, CompiledFunctionFrameInfo, CustomSection, CustomSectionProtection, CompiledFunction, CompiledFunctionFrameInfo, CustomSection, CustomSectionProtection,
FunctionBody, Relocation, RelocationKind, RelocationTarget, SectionBody, SectionIndex, FunctionBody, FunctionBodyData, InstructionAddressMap, Relocation, RelocationKind,
TrapInformation, RelocationTarget, SectionBody, SectionIndex, SourceLoc, TrapInformation,
}; };
use wasmer_types::{ use wasmer_types::{
entity::{EntityRef, PrimaryMap, SecondaryMap}, entity::{EntityRef, PrimaryMap, SecondaryMap},
@ -80,6 +81,12 @@ pub struct FuncGen<'a> {
/// A set of special labels for trapping. /// A set of special labels for trapping.
special_labels: SpecialLabelSet, special_labels: SpecialLabelSet,
/// The source location for the current operator
src_loc: u32,
/// All the InstructionAddressMap
instructions_address_map: Vec<InstructionAddressMap>,
} }
struct SpecialLabelSet { struct SpecialLabelSet {
@ -251,6 +258,11 @@ struct I2O1 {
} }
impl<'a> FuncGen<'a> { 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 { fn get_location_released(&mut self, loc: Location) -> Location {
self.machine.release_locations(&mut self.assembler, &[loc]); self.machine.release_locations(&mut self.assembler, &[loc]);
loc loc
@ -306,6 +318,11 @@ impl<'a> FuncGen<'a> {
for i in begin..end { for i in begin..end {
self.trap_table.offset_to_code.insert(i, code); self.trap_table.offset_to_code.insert(i, code);
} }
self.instructions_address_map.push(InstructionAddressMap {
srcloc: SourceLoc::new(self.src_loc),
code_offset: begin,
code_len: end - begin,
});
ret ret
} }
@ -313,6 +330,11 @@ impl<'a> FuncGen<'a> {
fn mark_address_with_trap_code(&mut self, code: TrapCode) { fn mark_address_with_trap_code(&mut self, code: TrapCode) {
let offset = self.assembler.get_offset().0; let offset = self.assembler.get_offset().0;
self.trap_table.offset_to_code.insert(offset, code); self.trap_table.offset_to_code.insert(offset, code);
self.instructions_address_map.push(InstructionAddressMap {
srcloc: SourceLoc::new(self.src_loc),
code_offset: offset,
code_len: 2, // TODO: Check this length
});
} }
/// Canonicalizes the floating point value at `input` into `output`. /// Canonicalizes the floating point value at `input` into `output`.
@ -379,16 +401,28 @@ impl<'a> FuncGen<'a> {
Location::Imm64(_) | Location::Imm32(_) => { Location::Imm64(_) | Location::Imm32(_) => {
self.assembler.emit_mov(sz, loc, Location::GPR(GPR::RCX)); // must not be used during div (rax, rdx) self.assembler.emit_mov(sz, loc, Location::GPR(GPR::RCX)); // must not be used during div (rax, rdx)
self.mark_trappable(); self.mark_trappable();
let offset = self.assembler.get_offset().0;
self.instructions_address_map.push(InstructionAddressMap {
srcloc: SourceLoc::new(self.src_loc),
code_offset: offset,
code_len: 2, // TODO: Check this length
});
self.trap_table self.trap_table
.offset_to_code .offset_to_code
.insert(self.assembler.get_offset().0, TrapCode::IntegerOverflow); .insert(offset, TrapCode::IntegerOverflow);
op(&mut self.assembler, sz, Location::GPR(GPR::RCX)); op(&mut self.assembler, sz, Location::GPR(GPR::RCX));
} }
_ => { _ => {
self.mark_trappable(); self.mark_trappable();
let offset = self.assembler.get_offset().0;
self.instructions_address_map.push(InstructionAddressMap {
srcloc: SourceLoc::new(self.src_loc),
code_offset: offset,
code_len: 2, // TODO: Check this length
});
self.trap_table self.trap_table
.offset_to_code .offset_to_code
.insert(self.assembler.get_offset().0, TrapCode::IntegerOverflow); .insert(offset, TrapCode::IntegerOverflow);
op(&mut self.assembler, sz, loc); op(&mut self.assembler, sz, loc);
} }
} }
@ -1473,16 +1507,28 @@ impl<'a> FuncGen<'a> {
); );
self.assembler.emit_label(trap_overflow); self.assembler.emit_label(trap_overflow);
let offset = self.assembler.get_offset().0;
self.instructions_address_map.push(InstructionAddressMap {
srcloc: SourceLoc::new(self.src_loc),
code_offset: offset,
code_len: 2, // TODO: Check this length
});
self.trap_table self.trap_table
.offset_to_code .offset_to_code
.insert(self.assembler.get_offset().0, TrapCode::IntegerOverflow); .insert(offset, TrapCode::IntegerOverflow);
self.assembler.emit_ud2(); self.assembler.emit_ud2();
self.assembler.emit_label(trap_badconv); self.assembler.emit_label(trap_badconv);
self.trap_table.offset_to_code.insert(
self.assembler.get_offset().0, let offset = self.assembler.get_offset().0;
TrapCode::BadConversionToInteger, self.instructions_address_map.push(InstructionAddressMap {
); srcloc: SourceLoc::new(self.src_loc),
code_offset: offset,
code_len: 2, // TODO: Check this length
});
self.trap_table
.offset_to_code
.insert(offset, TrapCode::BadConversionToInteger);
self.assembler.emit_ud2(); self.assembler.emit_ud2();
self.assembler.emit_label(end); self.assembler.emit_label(end);
@ -1622,16 +1668,27 @@ impl<'a> FuncGen<'a> {
); );
self.assembler.emit_label(trap_overflow); self.assembler.emit_label(trap_overflow);
let offset = self.assembler.get_offset().0;
self.instructions_address_map.push(InstructionAddressMap {
srcloc: SourceLoc::new(self.src_loc),
code_offset: offset,
code_len: 2, // TODO: Check this length
});
self.trap_table self.trap_table
.offset_to_code .offset_to_code
.insert(self.assembler.get_offset().0, TrapCode::IntegerOverflow); .insert(offset, TrapCode::IntegerOverflow);
self.assembler.emit_ud2(); self.assembler.emit_ud2();
self.assembler.emit_label(trap_badconv); self.assembler.emit_label(trap_badconv);
self.trap_table.offset_to_code.insert( let offset = self.assembler.get_offset().0;
self.assembler.get_offset().0, self.instructions_address_map.push(InstructionAddressMap {
TrapCode::BadConversionToInteger, srcloc: SourceLoc::new(self.src_loc),
); code_offset: offset,
code_len: 2, // TODO: Check this length
});
self.trap_table
.offset_to_code
.insert(offset, TrapCode::BadConversionToInteger);
self.assembler.emit_ud2(); self.assembler.emit_ud2();
self.assembler.emit_label(end); self.assembler.emit_label(end);
@ -1819,6 +1876,8 @@ impl<'a> FuncGen<'a> {
trap_table: TrapTable::default(), trap_table: TrapTable::default(),
relocations: vec![], relocations: vec![],
special_labels, special_labels,
src_loc: 0,
instructions_address_map: vec![],
}; };
fg.emit_head()?; fg.emit_head()?;
Ok(fg) Ok(fg)
@ -6128,10 +6187,15 @@ impl<'a> FuncGen<'a> {
} }
Operator::Unreachable => { Operator::Unreachable => {
self.mark_trappable(); self.mark_trappable();
self.trap_table.offset_to_code.insert( let offset = self.assembler.get_offset().0;
self.assembler.get_offset().0, self.instructions_address_map.push(InstructionAddressMap {
TrapCode::UnreachableCodeReached, srcloc: SourceLoc::new(self.src_loc),
); code_offset: offset,
code_len: 2, // TODO: Check this length
});
self.trap_table
.offset_to_code
.insert(offset, TrapCode::UnreachableCodeReached);
self.assembler.emit_ud2(); self.assembler.emit_ud2();
self.unreachable_depth = 1; self.unreachable_depth = 1;
} }
@ -8125,7 +8189,7 @@ impl<'a> FuncGen<'a> {
Ok(()) Ok(())
} }
pub fn finalize(mut self) -> CompiledFunction { pub fn finalize(mut self, data: &FunctionBodyData) -> CompiledFunction {
// Generate actual code for special labels. // Generate actual code for special labels.
self.assembler self.assembler
.emit_label(self.special_labels.integer_division_by_zero); .emit_label(self.special_labels.integer_division_by_zero);
@ -8153,6 +8217,11 @@ impl<'a> FuncGen<'a> {
// Notify the assembler backend to generate necessary code at end of function. // Notify the assembler backend to generate necessary code at end of function.
self.assembler.finalize_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 { CompiledFunction {
body: FunctionBody { body: FunctionBody {
body: self.assembler.finalize().unwrap().to_vec(), body: self.assembler.finalize().unwrap().to_vec(),
@ -8170,7 +8239,7 @@ impl<'a> FuncGen<'a> {
trap_code: code, trap_code: code,
}) })
.collect(), .collect(),
..Default::default() address_map,
}, },
} }
} }

View File

@ -106,11 +106,12 @@ impl Compiler for SinglepassCompiler {
.map_err(to_compile_error)?; .map_err(to_compile_error)?;
while generator.has_control_frames() { while generator.has_control_frames() {
generator.set_srcloc(reader.original_position() as u32);
let op = reader.read_operator().map_err(to_compile_error)?; let op = reader.read_operator().map_err(to_compile_error)?;
generator.feed_operator(op).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>>()? .collect::<Result<Vec<CompiledFunction>, CompileError>>()?
.into_iter() .into_iter()

View File

@ -8,6 +8,7 @@
//! Compared to Cranelift and LLVM, Singlepass compiles much faster but has worse //! Compared to Cranelift and LLVM, Singlepass compiles much faster but has worse
//! runtime performance. //! runtime performance.
mod address_map;
mod codegen_x64; mod codegen_x64;
mod common_decl; mod common_decl;
mod compiler; mod compiler;