Implement native call & fix stack alignment.

This commit is contained in:
losfair
2019-02-25 23:29:18 +08:00
parent da1a3fadb1
commit 80812e3809

View File

@ -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
); );
} }
} }