mirror of
https://github.com/fluencelabs/wasmer
synced 2025-06-26 23:21:35 +00:00
Implement native call & fix stack alignment.
This commit is contained in:
@ -36,9 +36,9 @@ lazy_static! {
|
|||||||
; je >_loop_end
|
; je >_loop_end
|
||||||
; mov eax, [rdi]
|
; mov eax, [rdi]
|
||||||
; mov [r8], eax
|
; mov [r8], eax
|
||||||
; add r8, 4
|
; add r8, 8
|
||||||
; add rdi, 4
|
; add rdi, 8
|
||||||
; sub rsi, 4
|
; sub rsi, 8
|
||||||
; jmp <_loop
|
; jmp <_loop
|
||||||
; _loop_end:
|
; _loop_end:
|
||||||
; jmp rdx
|
; jmp rdx
|
||||||
@ -327,7 +327,7 @@ impl X64FunctionCode {
|
|||||||
let size = get_size_of_type(&info.ty)?;
|
let size = get_size_of_type(&info.ty)?;
|
||||||
dynasm!(
|
dynasm!(
|
||||||
assembler
|
assembler
|
||||||
; add rsp, size as i32
|
; add rsp, 8
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -396,8 +396,7 @@ impl X64FunctionCode {
|
|||||||
} else if a.location.is_register() {
|
} else if a.location.is_register() {
|
||||||
dynasm!(
|
dynasm!(
|
||||||
assembler
|
assembler
|
||||||
; mov eax, [rsp]
|
; pop rax
|
||||||
; add rsp, 4
|
|
||||||
);
|
);
|
||||||
f(
|
f(
|
||||||
assembler,
|
assembler,
|
||||||
@ -411,15 +410,15 @@ impl X64FunctionCode {
|
|||||||
dynasm!(
|
dynasm!(
|
||||||
assembler
|
assembler
|
||||||
; push rcx
|
; push rcx
|
||||||
; mov ecx, [rsp + 12]
|
; mov ecx, [rsp + 16]
|
||||||
; mov eax, [rsp + 8]
|
; mov eax, [rsp + 8]
|
||||||
);
|
);
|
||||||
f(assembler, value_stack, Register::RCX, Register::RAX);
|
f(assembler, value_stack, Register::RCX, Register::RAX);
|
||||||
dynasm!(
|
dynasm!(
|
||||||
assembler
|
assembler
|
||||||
; mov [rsp + 12], ecx
|
; mov [rsp + 16], ecx
|
||||||
; pop rcx
|
; pop rcx
|
||||||
; add rsp, 4
|
; add rsp, 8
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -541,17 +540,10 @@ impl X64FunctionCode {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
ValueLocation::Stack => {
|
ValueLocation::Stack => {
|
||||||
if is_dword(get_size_of_type(&val.ty)?) {
|
dynasm!(
|
||||||
dynasm!(
|
assembler
|
||||||
assembler
|
; mov rax, [rsp]
|
||||||
; mov eax, [rsp]
|
);
|
||||||
);
|
|
||||||
} else {
|
|
||||||
dynasm!(
|
|
||||||
assembler
|
|
||||||
; mov rax, [rsp]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -572,19 +564,10 @@ impl X64FunctionCode {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
ValueLocation::Stack => {
|
ValueLocation::Stack => {
|
||||||
if is_dword(get_size_of_type(&val.ty)?) {
|
dynasm!(
|
||||||
dynasm!(
|
assembler
|
||||||
assembler
|
; pop rax
|
||||||
; mov eax, [rsp]
|
);
|
||||||
; add rsp, 4
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
dynasm!(
|
|
||||||
assembler
|
|
||||||
; mov rax, [rsp]
|
|
||||||
; add rsp, 8
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -606,19 +589,10 @@ impl X64FunctionCode {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
ValueLocation::Stack => {
|
ValueLocation::Stack => {
|
||||||
if is_dword(get_size_of_type(&ty)?) {
|
dynasm!(
|
||||||
dynasm!(
|
assembler
|
||||||
assembler
|
; push rax
|
||||||
; sub rsp, 4
|
);
|
||||||
; mov [rsp], eax
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
dynasm!(
|
|
||||||
assembler
|
|
||||||
; sub rsp, 8
|
|
||||||
; mov [rsp], rax
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -708,19 +682,10 @@ impl X64FunctionCode {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
ValueLocation::Stack => {
|
ValueLocation::Stack => {
|
||||||
if is_dword(get_size_of_type(&frame.returns[0])?) {
|
dynasm!(
|
||||||
dynasm!(
|
assembler
|
||||||
assembler
|
; push rax
|
||||||
; sub rsp, 4
|
);
|
||||||
; mov [rsp], eax
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
dynasm!(
|
|
||||||
assembler
|
|
||||||
; sub rsp, 8
|
|
||||||
; mov [rsp], rax
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -751,7 +716,7 @@ impl X64FunctionCode {
|
|||||||
for i in 0..value_stack.values.len() - frame.value_stack_depth_before {
|
for i in 0..value_stack.values.len() - frame.value_stack_depth_before {
|
||||||
let vi = value_stack.values[value_stack.values.len() - 1 - i];
|
let vi = value_stack.values[value_stack.values.len() - 1 - i];
|
||||||
if vi.location == ValueLocation::Stack {
|
if vi.location == ValueLocation::Stack {
|
||||||
sp_diff += get_size_of_type(&vi.ty)?;
|
sp_diff += 8
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -798,6 +763,67 @@ impl X64FunctionCode {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn emit_native_call_trampoline(
|
||||||
|
assembler: &mut Assembler,
|
||||||
|
value_stack: &mut ValueStack,
|
||||||
|
target: usize,
|
||||||
|
ctx1: usize,
|
||||||
|
ctx2: usize,
|
||||||
|
) -> Result<DynamicLabel, CodegenError> {
|
||||||
|
let label = assembler.new_dynamic_label();
|
||||||
|
|
||||||
|
dynasm!(
|
||||||
|
assembler
|
||||||
|
; =>label
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut saved_regs: Vec<Register> = Vec::new();
|
||||||
|
|
||||||
|
for v in &value_stack.values {
|
||||||
|
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!(
|
||||||
|
assembler
|
||||||
|
; mov rdi, QWORD (ctx1 as i64)
|
||||||
|
; mov rsi, QWORD (ctx2 as i64)
|
||||||
|
; lea rdx, [rsp + (saved_regs.len() * 8) as i32]
|
||||||
|
; mov rcx, rbp
|
||||||
|
; push rbp
|
||||||
|
; mov rbp, rsp
|
||||||
|
; mov rax, QWORD (0xfffffffffffffff0u64 as i64)
|
||||||
|
; and rsp, rax
|
||||||
|
; mov rax, QWORD (target as i64)
|
||||||
|
; call rax
|
||||||
|
; mov rsp, rbp
|
||||||
|
; pop rbp
|
||||||
|
);
|
||||||
|
|
||||||
|
for reg in saved_regs.iter().rev() {
|
||||||
|
dynasm!(
|
||||||
|
assembler
|
||||||
|
; pop Rq(*reg as u8)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
dynasm!(
|
||||||
|
assembler
|
||||||
|
; ret
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(label)
|
||||||
|
}
|
||||||
|
|
||||||
fn emit_call_raw(
|
fn emit_call_raw(
|
||||||
assembler: &mut Assembler,
|
assembler: &mut Assembler,
|
||||||
value_stack: &mut ValueStack,
|
value_stack: &mut ValueStack,
|
||||||
@ -805,10 +831,7 @@ impl X64FunctionCode {
|
|||||||
params: &[WpType],
|
params: &[WpType],
|
||||||
returns: &[WpType],
|
returns: &[WpType],
|
||||||
) -> Result<(), CodegenError> {
|
) -> Result<(), CodegenError> {
|
||||||
let mut total_size: usize = 0;
|
let total_size: usize = params.len() * 8;
|
||||||
for ty in params {
|
|
||||||
total_size += get_size_of_type(ty)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
if params.len() > value_stack.values.len() {
|
if params.len() > value_stack.values.len() {
|
||||||
return Err(CodegenError {
|
return Err(CodegenError {
|
||||||
@ -855,42 +878,26 @@ impl X64FunctionCode {
|
|||||||
message: "value type mismatch",
|
message: "value type mismatch",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
let size = get_size_of_type(ty)?;
|
|
||||||
|
|
||||||
match val.location {
|
match val.location {
|
||||||
ValueLocation::Register(x) => {
|
ValueLocation::Register(x) => {
|
||||||
let reg = Register::from_scratch_reg(x);
|
let reg = Register::from_scratch_reg(x);
|
||||||
if is_dword(size) {
|
dynasm!(
|
||||||
dynasm!(
|
assembler
|
||||||
assembler
|
; mov [rsp + offset as i32], Rq(reg as u8)
|
||||||
; mov [rsp + offset as i32], Rd(reg as u8)
|
);
|
||||||
);
|
|
||||||
} else {
|
|
||||||
dynasm!(
|
|
||||||
assembler
|
|
||||||
; mov [rsp + offset as i32], Rq(reg as u8)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ValueLocation::Stack => {
|
ValueLocation::Stack => {
|
||||||
if is_dword(size) {
|
dynasm!(
|
||||||
dynasm!(
|
assembler
|
||||||
assembler
|
; mov rax, [rsp + (total_size + 16 + saved_regs.len() * 8 + caller_stack_offset) as i32]
|
||||||
; mov eax, [rsp + (total_size + 16 + saved_regs.len() * 8 + caller_stack_offset) as i32]
|
; mov [rsp + offset as i32], rax
|
||||||
; mov [rsp + offset as i32], eax
|
);
|
||||||
);
|
caller_stack_offset += 8;
|
||||||
} else {
|
|
||||||
dynasm!(
|
|
||||||
assembler
|
|
||||||
; mov rax, [rsp + (total_size + 16 + saved_regs.len() * 8 + caller_stack_offset) as i32]
|
|
||||||
; mov [rsp + offset as i32], rax
|
|
||||||
);
|
|
||||||
}
|
|
||||||
caller_stack_offset += size;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
offset += size;
|
offset += 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_eq!(offset, total_size);
|
assert_eq!(offset, total_size);
|
||||||
@ -954,9 +961,8 @@ impl FunctionCodeGenerator for X64FunctionCode {
|
|||||||
/// - Locals in reversed order, callee initialized
|
/// - Locals in reversed order, callee initialized
|
||||||
fn feed_param(&mut self, ty: WpType) -> Result<(), CodegenError> {
|
fn feed_param(&mut self, ty: WpType) -> Result<(), CodegenError> {
|
||||||
let assembler = self.assembler.as_mut().unwrap();
|
let assembler = self.assembler.as_mut().unwrap();
|
||||||
let size = get_size_of_type(&ty)?;
|
|
||||||
|
|
||||||
self.current_stack_offset += size;
|
self.current_stack_offset += 8;
|
||||||
self.locals.push(Local {
|
self.locals.push(Local {
|
||||||
ty: ty,
|
ty: ty,
|
||||||
stack_offset: self.current_stack_offset,
|
stack_offset: self.current_stack_offset,
|
||||||
@ -970,25 +976,40 @@ impl FunctionCodeGenerator for X64FunctionCode {
|
|||||||
fn feed_local(&mut self, ty: WpType, n: usize) -> Result<(), CodegenError> {
|
fn feed_local(&mut self, ty: WpType, n: usize) -> Result<(), CodegenError> {
|
||||||
let assembler = self.assembler.as_mut().unwrap();
|
let assembler = self.assembler.as_mut().unwrap();
|
||||||
let size = get_size_of_type(&ty)?;
|
let size = get_size_of_type(&ty)?;
|
||||||
for _ in 0..n {
|
|
||||||
// FIXME: check range of n
|
if is_dword(size) {
|
||||||
self.current_stack_offset += size;
|
for _ in 0..n {
|
||||||
self.locals.push(Local {
|
// FIXME: check range of n
|
||||||
ty: ty,
|
self.current_stack_offset += 4;
|
||||||
stack_offset: self.current_stack_offset,
|
self.locals.push(Local {
|
||||||
});
|
ty: ty,
|
||||||
match size {
|
stack_offset: self.current_stack_offset,
|
||||||
4 => dynasm!(
|
});
|
||||||
|
dynasm!(
|
||||||
assembler
|
assembler
|
||||||
; sub rsp, 4
|
; sub rsp, 4
|
||||||
; mov DWORD [rsp], 0
|
; mov DWORD [rsp], 0
|
||||||
),
|
);
|
||||||
8 => dynasm!(
|
}
|
||||||
|
if n % 2 == 1 {
|
||||||
|
self.current_stack_offset += 4;
|
||||||
|
dynasm!(
|
||||||
assembler
|
assembler
|
||||||
; sub rsp, 8
|
; sub rsp, 4
|
||||||
; mov QWORD [rsp], 0
|
);
|
||||||
),
|
}
|
||||||
_ => unreachable!(),
|
} else {
|
||||||
|
for _ in 0..n {
|
||||||
|
// FIXME: check range of n
|
||||||
|
self.current_stack_offset += 8;
|
||||||
|
self.locals.push(Local {
|
||||||
|
ty: ty,
|
||||||
|
stack_offset: self.current_stack_offset,
|
||||||
|
});
|
||||||
|
dynasm!(
|
||||||
|
assembler
|
||||||
|
; push 0
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -1054,15 +1075,13 @@ impl FunctionCodeGenerator for X64FunctionCode {
|
|||||||
dynasm!(
|
dynasm!(
|
||||||
assembler
|
assembler
|
||||||
; mov eax, [rbp - (local.stack_offset as i32)]
|
; mov eax, [rbp - (local.stack_offset as i32)]
|
||||||
; sub rsp, 4
|
; push rax
|
||||||
; mov [rsp], eax
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
dynasm!(
|
dynasm!(
|
||||||
assembler
|
assembler
|
||||||
; mov rax, [rbp - (local.stack_offset as i32)]
|
; mov rax, [rbp - (local.stack_offset as i32)]
|
||||||
; sub rsp, 8
|
; push rax
|
||||||
; mov [rsp], rax
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1108,8 +1127,7 @@ impl FunctionCodeGenerator for X64FunctionCode {
|
|||||||
ValueLocation::Stack => {
|
ValueLocation::Stack => {
|
||||||
dynasm!(
|
dynasm!(
|
||||||
assembler
|
assembler
|
||||||
; sub rsp, 4
|
; push value
|
||||||
; mov DWORD [rsp], value
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user