Commit 0ca6181a authored by qinsoon's avatar qinsoon

NEWSTACK/NEWTHREAD implemented for x64, test_newthread_simple works

parent 79589ae4
......@@ -1012,6 +1012,23 @@ impl Value {
}
}
pub fn is_const_zero(&self) -> bool {
match self.v {
Value_::Constant(Constant::Int(val)) if val == 0 => true,
Value_::Constant(Constant::Double(val)) if val == 0f64 => true,
Value_::Constant(Constant::Float(val)) if val == 0f32 => true,
Value_::Constant(Constant::IntEx(ref vec)) => {
if vec.iter().all(|x| *x == 0) {
true
} else {
false
}
}
Value_::Constant(Constant::NullRef) => true,
_ => false
}
}
/// disguises a value as another type.
/// This is usually used for treat an integer type as an integer of a different length
/// This method is unsafe
......
......@@ -25,12 +25,16 @@ pub mod c {
/// computes arguments for the function signature,
/// returns a vector of CallConvResult for each argument type
pub fn compute_arguments(sig: &MuFuncSig) -> Vec<CallConvResult> {
compute_arguments_by_type(&sig.arg_tys)
}
pub fn compute_arguments_by_type(tys: &Vec<P<MuType>>) -> Vec<CallConvResult> {
let mut ret = vec![];
let mut gpr_arg_count = 0;
let mut fpr_arg_count = 0;
for ty in sig.arg_tys.iter() {
for ty in tys.iter() {
let arg_reg_group = RegGroup::get_from_ty(ty);
if arg_reg_group == RegGroup::GPR {
......@@ -127,9 +131,24 @@ pub mod c {
ret
}
pub fn compute_stack_args(sig: &MuFuncSig, vm: &VM) -> (ByteSize, Vec<ByteSize>) {
let callconv = compute_arguments(sig);
let mut stack_arg_tys = vec![];
for i in 0..callconv.len() {
let ref cc = callconv[i];
match cc {
&CallConvResult::STACK => stack_arg_tys.push(sig.arg_tys[i].clone()),
_ => {}
}
}
compute_stack_args_by_type(&stack_arg_tys, vm)
}
/// computes the return area on the stack for the function signature,
/// returns a tuple of (size, callcand offset for each stack arguments)
pub fn compute_stack_args(
pub fn compute_stack_args_by_type(
stack_arg_tys: &Vec<P<MuType>>,
vm: &VM
) -> (ByteSize, Vec<ByteSize>) {
......
......@@ -17,36 +17,50 @@
#if defined (__linux__)
#define CNAME(n) n
#define CNAME(n) n
.macro begin_func n
.text
.globl CNAME(\n)
.type CNAME(\n),@function
.balign 16
.macro begin_func n
.text
.globl CNAME(\n)
.type CNAME(\n),@function
.balign 16
CNAME(\n):
.endm
.endm
.macro end_func n
.size CNAME(\n), .-CNAME(\n)
.endm
.macro end_func n
.size CNAME(\n), .-CNAME(\n)
.endm
.macro jmp_to target
jmp CNAME(\target@PLT)
.endm
.macro call_to target
call CNAME(\target@PLT)
.endm
#elif defined (__APPLE__)
#define CNAME(n) _##n
#define CNAME(n) _##n
.macro begin_func n
.text
.globl CNAME(\n)
.balign 4
.macro begin_func n
.text
.globl CNAME(\n)
.balign 4
CNAME(\n):
.endm
.endm
.macro end_func n
.endm
.macro end_func n
.endm
.macro jmp_to target
jmp CNAME(\target)
.endm
.macro call_to target
call CNAME(\target)
.endm
#else
#error "Only Linux and OSX are supported."
#error "Only Linux and OSX are supported."
#endif
; vim: ft=asm
......@@ -75,10 +75,9 @@ begin_func muthread_start_normal
BR LR
end_func muthread_start_normal
# starts a muthread that passes values to the target
# muthread_start_throw(exception: Address, new_sp: Address, old_sp_loc: &mut Adress)
# X0 X1 X2
# starts a muthread with an exception thrown
# muthread_start_exceptional(exception: Address, new_sp: Address, old_sp_loc: &mut Adress)
# X0 X1 X2
begin_func muthread_start_exceptional
enter_frame
push_callee_saved
......
......@@ -14,114 +14,135 @@
#include "asm_common_x64.S.inc"
# _get_current_frame_bp() -> Address
begin_func get_current_frame_bp
movq %rbp, %rax
ret
end_func get_current_frame_bp
# muthread_start_normal(new_sp: Address, old_sp_loc: Address)
# %rdi %rsi
begin_func muthread_start_normal
# -- on old stack --
# C calling convention - enter frame
pushq %rbp
movq %rsp, %rbp
# save callee saved registers
pushq %rbx
pushq %r12
pushq %r13
pushq %r14
pushq %r15
# save sp to old_sp_loc
movq %rsp, 0(%rsi)
# switch to new stack
movq %rdi, %rsp
# -- on new stack --
# arguments (reverse order of thread.rs - runtime_load_args)
popq %r9
popq %r8
popq %rcx
popq %rdx
popq %rsi
popq %rdi
movsd 0(%rsp), %xmm7
movsd 8(%rsp), %xmm6
movsd 16(%rsp), %xmm5
movsd 24(%rsp), %xmm4
movsd 32(%rsp), %xmm3
movsd 40(%rsp), %xmm2
movsd 48(%rsp), %xmm1
movsd 56(%rsp), %xmm0
add $64, %rsp
# at this point new stack is clean (no intermediate values)
# on stack it look like this
# SP -> 0
# entry_func
# pop 0 as rbp
popq %rbp
# pop entry func to r10 (this is a caller saved register, it is save for us to use)
popq %r10
call *%r10
# -- on old stack --
# C calling convention - enter frame
pushq %rbp
movq %rsp, %rbp
# save callee saved registers
pushq %rbx
pushq %r12
pushq %r13
pushq %r14
pushq %r15
# save sp to old_sp_loc
movq %rsp, 0(%rsi)
# switch to new stack
movq %rdi, %rsp
# -- on new stack --
# arguments (reverse order of thread.rs - runtime_load_args)
popq %r9
popq %r8
popq %rcx
popq %rdx
popq %rsi
popq %rdi
movsd 0(%rsp), %xmm7
movsd 8(%rsp), %xmm6
movsd 16(%rsp), %xmm5
movsd 24(%rsp), %xmm4
movsd 32(%rsp), %xmm3
movsd 40(%rsp), %xmm2
movsd 48(%rsp), %xmm1
movsd 56(%rsp), %xmm0
add $64, %rsp
# at this point new stack is clean (no intermediate values)
# on stack it look like this
# SP -> 0
# entry_func
# pop 0 as rbp
popq %rbp
# pop entry func to r10 (this is a caller saved register, it is save for us to use)
popq %r10
call *%r10
end_func muthread_start_normal
# starts a muthread with an exception thrown
# muthread_start_exceptional(exception: Address, new_sp: Address, old_sp_loc: &mut Address)
# %rdi %rsi %rdx
begin_func muthread_start_exceptional
# -- on old stack --
# C calling convention - enter frame
pushq %rbp
movq %rsp, %rbp
# save callee saved registers
pushq %rbx
pushq %r12
pushq %r13
pushq %r14
pushq %r15
# save SP to old_sp_loc
movq %rsp, (%rdx)
# swap to new stack
movq %rsi, %rsp
subq 48, %rsp
jmp_to throw_exception_internal
end_func muthread_start_exceptional
# muentry_thread_exit(old_sp: Address)
# %rdi
begin_func muentry_thread_exit
movq %rdi, %rsp
movq %rdi, %rsp
popq %r15
popq %r14
popq %r13
popq %r12
popq %rbx
popq %r15
popq %r14
popq %r13
popq %r12
popq %rbx
popq %rbp
ret
popq %rbp
ret
end_func muentry_thread_exit
# _get_current_frame_bp() -> Address
begin_func get_current_frame_bp
movq %rbp, %rax
ret
end_func get_current_frame_bp
# muentry_throw_exception(obj: Address)
# %rdi
begin_func muentry_throw_exception
# save all callee-saved
pushq %rbp
movq %rsp, %rbp
pushq %rbx
pushq %r12
pushq %r13
pushq %r14
pushq %r15
# %rsp points to %rbx, pass this as 2nd argument
movq %rbp, %rsi
#if defined (__linux__)
jmp CNAME(throw_exception_internal@PLT)
#elif defined (__APPLE__)
jmp CNAME(throw_exception_internal)
#else
#error "Only Linux and OSX are supported. "
#endif
# won't return
# save all callee-saved
pushq %rbp
movq %rsp, %rbp
pushq %rbx
pushq %r12
pushq %r13
pushq %r14
pushq %r15
# %rsp points to %rbx, pass this as 2nd argument
movq %rbp, %rsi
jmp_to throw_exception_internal
# won't return
end_func muentry_throw_exception
# _exception_restore(dest: Address, callee_saved: *const Word, rsp: Address) -> !
# %rdi %rsi %rdx
# callee_saved: [rbx, rbp, r12, r13, r14, r15]
begin_func exception_restore
movq 0(%rsi), %rbp
movq -8(%rsi),%rbx
movq -16(%rsi),%r12
movq -24(%rsi),%r13
movq -32(%rsi),%r14
movq -40(%rsi),%r15
movq %rdx, %rsp
jmpq *%rdi
movq 0(%rsi), %rbp
movq -8(%rsi),%rbx
movq -16(%rsi),%r12
movq -24(%rsi),%r13
movq -32(%rsi),%r14
movq -40(%rsi),%r15
movq %rdx, %rsp
jmpq *%rdi
end_func exception_restore
\ No newline at end of file
......@@ -185,9 +185,9 @@ impl MuStack {
/// sets up arguments for the stack's entry function, so it is ready to be executed.
/// We use a special calling convention for the entry function: we push all the argument
/// registers for the platform to the stack. If the argument register is used, we get
/// its value and push the value. Otherwise we push an empty value (0). swap_to_mu_stack
/// its value and push the value. Otherwise we push an empty value (0). muthread_start_normal
/// will consume those values on the stack by popping them one by one.
/// NOTE: any changes to here need to be reflected in swap_to_mu_stack, which consumes
/// NOTE: any changes to here need to be reflected in muthread_start_normal, which consumes
/// those values pushed to the stack
pub fn setup_args(&mut self, vals: Vec<ValueLocation>) {
use utils::Word;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment