Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added basic AddressMap support for singlepass #1870

Merged
merged 22 commits into from
Dec 8, 2020
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
7745875
Added address map instructions for traps in singlepass
syrusakbary Dec 4, 2020
55d001d
Debug frameinfos
syrusakbary Dec 4, 2020
917eadb
Improve debugging of FunctionInfo
syrusakbary Dec 4, 2020
2178f27
Added stackoverflow traps on function calls in singlepass
syrusakbary Dec 4, 2020
cc0d595
Fixed last tests in Linux
syrusakbary Dec 4, 2020
6eb897d
Revert "Debug frameinfos"
syrusakbary Dec 4, 2020
24960b7
Merge branch 'master' into singlepass-addressmap
syrusakbary Dec 4, 2020
bdb0a93
Update address_map.rs
syrusakbary Dec 4, 2020
9a5336f
Update lib/compiler-singlepass/src/codegen_x64.rs
syrusakbary Dec 4, 2020
34cf011
Update lib/compiler-singlepass/src/codegen_x64.rs
syrusakbary Dec 4, 2020
0893de0
Update lib/compiler-singlepass/src/codegen_x64.rs
syrusakbary Dec 4, 2020
6e38d72
Update lib/compiler-singlepass/src/codegen_x64.rs
syrusakbary Dec 4, 2020
785f41b
Update lib/compiler-singlepass/src/codegen_x64.rs
syrusakbary Dec 4, 2020
b7eb928
Update lib/compiler-singlepass/src/codegen_x64.rs
syrusakbary Dec 4, 2020
f119af7
Update lib/compiler-singlepass/src/codegen_x64.rs
syrusakbary Dec 4, 2020
263504d
Improved instruction mapping
syrusakbary Dec 8, 2020
30f622f
Merge branch 'master' of github.com:wasmerio/wasmer into singlepass-a…
syrusakbary Dec 8, 2020
b54df7e
Fixed lint issues in singlepass
syrusakbary Dec 8, 2020
f6c0d4f
Fix lint in singlepass
syrusakbary Dec 8, 2020
5a2c14a
Update lib/compiler-singlepass/src/codegen_x64.rs
syrusakbary Dec 8, 2020
bfbb0e1
Update lib/compiler-singlepass/src/codegen_x64.rs
syrusakbary Dec 8, 2020
f2356ed
Fix linting issues
syrusakbary Dec 8, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 artificial srcloc for function start/end to identify boundary
// within module. It will wrap around if byte code is larger than 4 GB.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you reword this comment? This comment turns up cranelift source code if you search for "Generate artificial srcloc for" which is unfortunate, given that the rest of the function doesn't match anything in cranelift.

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,
}
}
138 changes: 118 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,12 @@ pub struct FuncGen<'a> {

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

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

/// All the InstructionAddressMap
syrusakbary marked this conversation as resolved.
Show resolved Hide resolved
instructions_address_map: Vec<InstructionAddressMap>,
}

struct SpecialLabelSet {
Expand Down Expand Up @@ -251,6 +258,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 +318,23 @@ impl<'a> FuncGen<'a> {
for i in begin..end {
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,
});
nlewycky marked this conversation as resolved.
Show resolved Hide resolved
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.instructions_address_map.push(InstructionAddressMap {
srcloc: SourceLoc::new(self.src_loc),
code_offset: offset,
code_len: 2, // TODO: Check this length
syrusakbary marked this conversation as resolved.
Show resolved Hide resolved
});
}

/// Canonicalizes the floating point value at `input` into `output`.
Expand Down Expand Up @@ -379,16 +401,28 @@ 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.instructions_address_map.push(InstructionAddressMap {
srcloc: SourceLoc::new(self.src_loc),
code_offset: offset,
code_len: 2, // TODO: Check this length
syrusakbary marked this conversation as resolved.
Show resolved Hide resolved
});
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_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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a problem (see earlier comment about DIV lengths).

});
self.trap_table
.offset_to_code
.insert(self.assembler.get_offset().0, TrapCode::IntegerOverflow);
.insert(offset, TrapCode::IntegerOverflow);
op(&mut self.assembler, sz, loc);
}
}
Expand Down Expand Up @@ -1473,16 +1507,28 @@ impl<'a> FuncGen<'a> {
);

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
syrusakbary marked this conversation as resolved.
Show resolved Hide resolved
});
self.trap_table
.offset_to_code
.insert(self.assembler.get_offset().0, TrapCode::IntegerOverflow);
.insert(offset, TrapCode::IntegerOverflow);
self.assembler.emit_ud2();

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.instructions_address_map.push(InstructionAddressMap {
srcloc: SourceLoc::new(self.src_loc),
code_offset: offset,
code_len: 2, // TODO: Check this length
syrusakbary marked this conversation as resolved.
Show resolved Hide resolved
});
self.trap_table
.offset_to_code
.insert(offset, TrapCode::BadConversionToInteger);
self.assembler.emit_ud2();

self.assembler.emit_label(end);
Expand Down Expand Up @@ -1622,16 +1668,27 @@ impl<'a> FuncGen<'a> {
);

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
syrusakbary marked this conversation as resolved.
Show resolved Hide resolved
});
self.trap_table
.offset_to_code
.insert(self.assembler.get_offset().0, TrapCode::IntegerOverflow);
.insert(offset, TrapCode::IntegerOverflow);
self.assembler.emit_ud2();

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.instructions_address_map.push(InstructionAddressMap {
srcloc: SourceLoc::new(self.src_loc),
code_offset: offset,
code_len: 2, // TODO: Check this length
syrusakbary marked this conversation as resolved.
Show resolved Hide resolved
});
self.trap_table
.offset_to_code
.insert(offset, TrapCode::BadConversionToInteger);
self.assembler.emit_ud2();

self.assembler.emit_label(end);
Expand Down Expand Up @@ -1754,6 +1811,17 @@ 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 for sake of simplicity.
syrusakbary marked this conversation as resolved.
Show resolved Hide resolved
syrusakbary marked this conversation as resolved.
Show resolved Hide resolved
self.instructions_address_map.push(InstructionAddressMap {
srcloc: SourceLoc::new(self.src_loc),
code_offset: 0,
code_len: self.assembler.get_offset().0,
});
self.trap_table
.offset_to_code
.insert(0, TrapCode::StackOverflow);

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 Down Expand Up @@ -1819,6 +1887,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,6 +5235,15 @@ impl<'a> FuncGen<'a> {

self.emit_call_sysv(
|this| {
let offset = this.assembler.get_offset().0;
this.instructions_address_map.push(InstructionAddressMap {
srcloc: SourceLoc::new(this.src_loc),
code_offset: offset,
code_len: 3,
});
this.trap_table
.offset_to_code
.insert(offset, TrapCode::StackOverflow);
this.assembler.emit_call_location(Location::GPR(GPR::RAX));
},
params.iter().copied(),
Expand Down Expand Up @@ -5358,6 +5437,15 @@ impl<'a> FuncGen<'a> {
),
);
} else {
let offset = this.assembler.get_offset().0;
this.instructions_address_map.push(InstructionAddressMap {
srcloc: SourceLoc::new(this.src_loc),
code_offset: offset,
code_len: 3,
syrusakbary marked this conversation as resolved.
Show resolved Hide resolved
});
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,
Expand Down Expand Up @@ -6128,10 +6216,15 @@ 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.instructions_address_map.push(InstructionAddressMap {
srcloc: SourceLoc::new(self.src_loc),
code_offset: offset,
code_len: 2, // TODO: Check this length
syrusakbary marked this conversation as resolved.
Show resolved Hide resolved
});
self.trap_table
.offset_to_code
.insert(offset, TrapCode::UnreachableCodeReached);
self.assembler.emit_ud2();
self.unreachable_depth = 1;
}
Expand Down Expand Up @@ -8125,7 +8218,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 +8246,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 +8268,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 @@ -106,11 +106,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