mirror of
https://github.com/mii443/wasmer.git
synced 2025-08-30 20:29:31 +00:00
Added address map instructions for traps in singlepass
This commit is contained in:
23
lib/compiler-singlepass/src/address_map.rs
Normal file
23
lib/compiler-singlepass/src/address_map.rs
Normal 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,
|
||||||
|
}
|
||||||
|
}
|
@ -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,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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()
|
||||||
|
@ -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;
|
||||||
|
Reference in New Issue
Block a user