mirror of
https://github.com/fluencelabs/wasmer
synced 2025-06-25 14:41:32 +00:00
Native trampolines.
This commit is contained in:
@ -121,16 +121,28 @@ impl Register {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[repr(u64)]
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
pub enum TrapCode {
|
||||||
|
Unreachable,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct NativeTrampolines {
|
||||||
|
trap_unreachable: DynamicLabel,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct X64ModuleCodeGenerator {
|
pub struct X64ModuleCodeGenerator {
|
||||||
functions: Vec<X64FunctionCode>,
|
functions: Vec<X64FunctionCode>,
|
||||||
signatures: Option<Arc<Map<SigIndex, Arc<FuncSig>>>>,
|
signatures: Option<Arc<Map<SigIndex, Arc<FuncSig>>>>,
|
||||||
function_signatures: Option<Arc<Map<FuncIndex, SigIndex>>>,
|
function_signatures: Option<Arc<Map<FuncIndex, SigIndex>>>,
|
||||||
|
assembler: Option<Assembler>,
|
||||||
|
native_trampolines: Arc<NativeTrampolines>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct X64FunctionCode {
|
pub struct X64FunctionCode {
|
||||||
signatures: Arc<Map<SigIndex, Arc<FuncSig>>>,
|
signatures: Arc<Map<SigIndex, Arc<FuncSig>>>,
|
||||||
function_signatures: Arc<Map<FuncIndex, SigIndex>>,
|
function_signatures: Arc<Map<FuncIndex, SigIndex>>,
|
||||||
|
native_trampolines: Arc<NativeTrampolines>,
|
||||||
|
|
||||||
id: usize,
|
id: usize,
|
||||||
begin_label: DynamicLabel,
|
begin_label: DynamicLabel,
|
||||||
@ -238,7 +250,23 @@ struct Local {
|
|||||||
|
|
||||||
impl X64ModuleCodeGenerator {
|
impl X64ModuleCodeGenerator {
|
||||||
pub fn new() -> X64ModuleCodeGenerator {
|
pub fn new() -> X64ModuleCodeGenerator {
|
||||||
X64ModuleCodeGenerator::default()
|
let mut assembler = Assembler::new().unwrap();
|
||||||
|
let nt = NativeTrampolines {
|
||||||
|
trap_unreachable: X64FunctionCode::emit_native_call_trampoline(
|
||||||
|
&mut assembler,
|
||||||
|
do_trap,
|
||||||
|
0usize,
|
||||||
|
TrapCode::Unreachable,
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
X64ModuleCodeGenerator {
|
||||||
|
functions: vec![],
|
||||||
|
signatures: None,
|
||||||
|
function_signatures: None,
|
||||||
|
assembler: Some(assembler),
|
||||||
|
native_trampolines: Arc::new(nt),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,18 +278,7 @@ impl ModuleCodeGenerator<X64FunctionCode, X64ExecutionContext> for X64ModuleCode
|
|||||||
x.function_labels.take().unwrap(),
|
x.function_labels.take().unwrap(),
|
||||||
x.br_table_data.take().unwrap(),
|
x.br_table_data.take().unwrap(),
|
||||||
),
|
),
|
||||||
None => (
|
None => (self.assembler.take().unwrap(), HashMap::new(), vec![]),
|
||||||
match Assembler::new() {
|
|
||||||
Ok(x) => x,
|
|
||||||
Err(_) => {
|
|
||||||
return Err(CodegenError {
|
|
||||||
message: "cannot initialize assembler",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
HashMap::new(),
|
|
||||||
vec![],
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
let begin_label = *function_labels
|
let begin_label = *function_labels
|
||||||
.entry(self.functions.len())
|
.entry(self.functions.len())
|
||||||
@ -275,6 +292,7 @@ impl ModuleCodeGenerator<X64FunctionCode, X64ExecutionContext> for X64ModuleCode
|
|||||||
let code = X64FunctionCode {
|
let code = X64FunctionCode {
|
||||||
signatures: self.signatures.as_ref().unwrap().clone(),
|
signatures: self.signatures.as_ref().unwrap().clone(),
|
||||||
function_signatures: self.function_signatures.as_ref().unwrap().clone(),
|
function_signatures: self.function_signatures.as_ref().unwrap().clone(),
|
||||||
|
native_trampolines: self.native_trampolines.clone(),
|
||||||
|
|
||||||
id: self.functions.len(),
|
id: self.functions.len(),
|
||||||
begin_label: begin_label,
|
begin_label: begin_label,
|
||||||
@ -778,13 +796,17 @@ impl X64FunctionCode {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_native_call_trampoline(
|
fn emit_native_call_trampoline<A: Copy + Sized, B: Copy + Sized>(
|
||||||
assembler: &mut Assembler,
|
assembler: &mut Assembler,
|
||||||
value_stack: &mut ValueStack,
|
target: unsafe extern "C" fn(
|
||||||
target: usize,
|
ctx1: A,
|
||||||
ctx1: usize,
|
ctx2: B,
|
||||||
ctx2: usize,
|
stack_top: *mut u8,
|
||||||
) -> Result<DynamicLabel, CodegenError> {
|
stack_base: *mut u8,
|
||||||
|
) -> u64,
|
||||||
|
ctx1: A,
|
||||||
|
ctx2: B,
|
||||||
|
) -> DynamicLabel {
|
||||||
let label = assembler.new_dynamic_label();
|
let label = assembler.new_dynamic_label();
|
||||||
|
|
||||||
dynasm!(
|
dynasm!(
|
||||||
@ -792,27 +814,15 @@ impl X64FunctionCode {
|
|||||||
; =>label
|
; =>label
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut saved_regs: Vec<Register> = Vec::new();
|
// FIXME: Check at compile time.
|
||||||
|
assert_eq!(::std::mem::size_of::<A>(), ::std::mem::size_of::<i64>());
|
||||||
for v in &value_stack.values {
|
assert_eq!(::std::mem::size_of::<B>(), ::std::mem::size_of::<i64>());
|
||||||
match v.location {
|
|
||||||
ValueLocation::Register(x) => {
|
|
||||||
let reg = Register::from_scratch_reg(x);
|
|
||||||
dynasm!(
|
|
||||||
assembler
|
|
||||||
; push Rq(reg as u8)
|
|
||||||
);
|
|
||||||
saved_regs.push(reg);
|
|
||||||
}
|
|
||||||
ValueLocation::Stack => break,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dynasm!(
|
dynasm!(
|
||||||
assembler
|
assembler
|
||||||
; mov rdi, QWORD (ctx1 as i64)
|
; mov rdi, QWORD (unsafe { ::std::mem::transmute_copy::<A, i64>(&ctx1) })
|
||||||
; mov rsi, QWORD (ctx2 as i64)
|
; mov rsi, QWORD (unsafe { ::std::mem::transmute_copy::<B, i64>(&ctx2) })
|
||||||
; lea rdx, [rsp + (saved_regs.len() * 8) as i32]
|
; mov rdx, rsp
|
||||||
; mov rcx, rbp
|
; mov rcx, rbp
|
||||||
; push rbp
|
; push rbp
|
||||||
; mov rbp, rsp
|
; mov rbp, rsp
|
||||||
@ -824,19 +834,12 @@ impl X64FunctionCode {
|
|||||||
; pop rbp
|
; pop rbp
|
||||||
);
|
);
|
||||||
|
|
||||||
for reg in saved_regs.iter().rev() {
|
|
||||||
dynasm!(
|
|
||||||
assembler
|
|
||||||
; pop Rq(*reg as u8)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
dynasm!(
|
dynasm!(
|
||||||
assembler
|
assembler
|
||||||
; ret
|
; ret
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(label)
|
label
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_call_raw(
|
fn emit_call_raw(
|
||||||
@ -1439,10 +1442,13 @@ impl FunctionCodeGenerator for X64FunctionCode {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
Operator::Unreachable => {
|
Operator::Unreachable => {
|
||||||
dynasm!(
|
Self::emit_call_raw(
|
||||||
assembler
|
assembler,
|
||||||
; ud2
|
&mut self.value_stack,
|
||||||
);
|
self.native_trampolines.trap_unreachable,
|
||||||
|
&[],
|
||||||
|
&[],
|
||||||
|
)?;
|
||||||
self.unreachable_depth = 1;
|
self.unreachable_depth = 1;
|
||||||
}
|
}
|
||||||
Operator::Drop => {
|
Operator::Drop => {
|
||||||
@ -1667,3 +1673,12 @@ fn type_to_wp_type(ty: Type) -> WpType {
|
|||||||
Type::F64 => WpType::F64,
|
Type::F64 => WpType::F64,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" fn do_trap(
|
||||||
|
ctx1: usize,
|
||||||
|
ctx2: TrapCode,
|
||||||
|
stack_top: *mut u8,
|
||||||
|
stack_base: *mut u8,
|
||||||
|
) -> u64 {
|
||||||
|
panic!("TRAP CODE: {:?}", ctx2);
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user