Dynamic function support for singlepass.

This commit is contained in:
losfair
2020-05-27 23:56:39 +08:00
parent 58e0c30c34
commit f1883508e5
2 changed files with 113 additions and 10 deletions

View File

@@ -8349,11 +8349,104 @@ pub fn gen_std_trampoline(sig: FunctionType) -> FunctionBody {
}
}
/// Generates dynamic import function call trampoline for a function type.
pub fn gen_std_dynamic_import_trampoline(
vmoffsets: &VMOffsets,
sig: &FunctionType,
) -> FunctionBody {
let mut a = Assembler::new().unwrap();
// Allocate argument array.
let stack_offset: usize = 16 * std::cmp::max(sig.params().len(), sig.results().len()) + 8; // 16 bytes each + 8 bytes sysv call padding
a.emit_sub(
Size::S64,
Location::Imm32(stack_offset as _),
Location::GPR(GPR::RSP),
);
// Copy arguments.
if sig.params().len() > 0 {
let mut argalloc = ArgumentRegisterAllocator::default();
argalloc.next(Type::I32).unwrap(); // skip VMContext
let mut stack_param_count: usize = 0;
for (i, ty) in sig.params().iter().enumerate() {
let source_loc = match argalloc.next(*ty) {
Some(X64Register::GPR(gpr)) => Location::GPR(gpr),
Some(X64Register::XMM(xmm)) => Location::XMM(xmm),
None => {
a.emit_mov(
Size::S64,
Location::Memory(GPR::RSP, (stack_offset + 8 + stack_param_count * 8) as _),
Location::GPR(GPR::RAX),
);
stack_param_count += 1;
Location::GPR(GPR::RAX)
}
};
a.emit_mov(
Size::S64,
source_loc,
Location::Memory(GPR::RSP, (i * 16) as _),
);
// Zero upper 64 bits.
a.emit_mov(
Size::S64,
Location::Imm32(0),
Location::Memory(GPR::RSP, (i * 16 + 8) as _),
);
}
}
// Load target address.
a.emit_mov(
Size::S64,
Location::Memory(
GPR::RDI,
vmoffsets.vmdynamicfunction_import_context_address() as i32,
),
Location::GPR(GPR::RAX),
);
// Load values array.
a.emit_mov(Size::S64, Location::GPR(GPR::RSP), Location::GPR(GPR::RSI));
// Call target.
a.emit_call_location(Location::GPR(GPR::RAX));
// Fetch return value.
if sig.results().len() > 0 {
assert_eq!(sig.results().len(), 1);
a.emit_mov(
Size::S64,
Location::Memory(GPR::RSP, 0),
Location::GPR(GPR::RAX),
);
}
// Release values array.
a.emit_add(
Size::S64,
Location::Imm32(stack_offset as _),
Location::GPR(GPR::RSP),
);
// Return.
a.emit_ret();
FunctionBody {
body: a.finalize().unwrap().to_vec(),
unwind_info: None,
}
}
// Singlepass calls import functions through a trampoline.
pub fn gen_import_call_trampoline(
vmoffsets: &VMOffsets,
index: FunctionIndex,
sig: FunctionType,
sig: &FunctionType,
) -> CustomSection {
let mut a = Assembler::new().unwrap();