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 { ...@@ -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. /// disguises a value as another type.
/// This is usually used for treat an integer type as an integer of a different length /// This is usually used for treat an integer type as an integer of a different length
/// This method is unsafe /// This method is unsafe
......
...@@ -25,12 +25,16 @@ pub mod c { ...@@ -25,12 +25,16 @@ pub mod c {
/// computes arguments for the function signature, /// computes arguments for the function signature,
/// returns a vector of CallConvResult for each argument type /// returns a vector of CallConvResult for each argument type
pub fn compute_arguments(sig: &MuFuncSig) -> Vec<CallConvResult> { 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 ret = vec![];
let mut gpr_arg_count = 0; let mut gpr_arg_count = 0;
let mut fpr_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); let arg_reg_group = RegGroup::get_from_ty(ty);
if arg_reg_group == RegGroup::GPR { if arg_reg_group == RegGroup::GPR {
...@@ -127,9 +131,24 @@ pub mod c { ...@@ -127,9 +131,24 @@ pub mod c {
ret 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, /// computes the return area on the stack for the function signature,
/// returns a tuple of (size, callcand offset for each stack arguments) /// 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>>, stack_arg_tys: &Vec<P<MuType>>,
vm: &VM vm: &VM
) -> (ByteSize, Vec<ByteSize>) { ) -> (ByteSize, Vec<ByteSize>) {
......
...@@ -17,36 +17,50 @@ ...@@ -17,36 +17,50 @@
#if defined (__linux__) #if defined (__linux__)
#define CNAME(n) n #define CNAME(n) n
.macro begin_func n .macro begin_func n
.text .text
.globl CNAME(\n) .globl CNAME(\n)
.type CNAME(\n),@function .type CNAME(\n),@function
.balign 16 .balign 16
CNAME(\n): CNAME(\n):
.endm .endm
.macro end_func n .macro end_func n
.size CNAME(\n), .-CNAME(\n) .size CNAME(\n), .-CNAME(\n)
.endm .endm
.macro jmp_to target
jmp CNAME(\target@PLT)
.endm
.macro call_to target
call CNAME(\target@PLT)
.endm
#elif defined (__APPLE__) #elif defined (__APPLE__)
#define CNAME(n) _##n #define CNAME(n) _##n
.macro begin_func n .macro begin_func n
.text .text
.globl CNAME(\n) .globl CNAME(\n)
.balign 4 .balign 4
CNAME(\n): CNAME(\n):
.endm .endm
.macro end_func n
.endm
.macro end_func n .macro jmp_to target
.endm jmp CNAME(\target)
.endm
.macro call_to target
call CNAME(\target)
.endm
#else #else
#error "Only Linux and OSX are supported." #error "Only Linux and OSX are supported."
#endif #endif
; vim: ft=asm
...@@ -75,10 +75,9 @@ begin_func muthread_start_normal ...@@ -75,10 +75,9 @@ begin_func muthread_start_normal
BR LR BR LR
end_func muthread_start_normal end_func muthread_start_normal
# starts a muthread with an exception thrown
# starts a muthread that passes values to the target # muthread_start_exceptional(exception: Address, new_sp: Address, old_sp_loc: &mut Adress)
# muthread_start_throw(exception: Address, new_sp: Address, old_sp_loc: &mut Adress) # X0 X1 X2
# X0 X1 X2
begin_func muthread_start_exceptional begin_func muthread_start_exceptional
enter_frame enter_frame
push_callee_saved push_callee_saved
......
...@@ -14,114 +14,135 @@ ...@@ -14,114 +14,135 @@
#include "asm_common_x64.S.inc" #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) # muthread_start_normal(new_sp: Address, old_sp_loc: Address)
# %rdi %rsi # %rdi %rsi
begin_func muthread_start_normal begin_func muthread_start_normal
# -- on old stack -- # -- on old stack --
# C calling convention - enter frame # C calling convention - enter frame
pushq %rbp pushq %rbp
movq %rsp, %rbp movq %rsp, %rbp
# save callee saved registers # save callee saved registers
pushq %rbx pushq %rbx
pushq %r12 pushq %r12
pushq %r13 pushq %r13
pushq %r14 pushq %r14
pushq %r15 pushq %r15
# save sp to old_sp_loc # save sp to old_sp_loc
movq %rsp, 0(%rsi) movq %rsp, 0(%rsi)
# switch to new stack # switch to new stack
movq %rdi, %rsp movq %rdi, %rsp
# -- on new stack -- # -- on new stack --
# arguments (reverse order of thread.rs - runtime_load_args) # arguments (reverse order of thread.rs - runtime_load_args)
popq %r9 popq %r9
popq %r8 popq %r8
popq %rcx popq %rcx
popq %rdx popq %rdx
popq %rsi popq %rsi
popq %rdi popq %rdi
movsd 0(%rsp), %xmm7 movsd 0(%rsp), %xmm7
movsd 8(%rsp), %xmm6 movsd 8(%rsp), %xmm6
movsd 16(%rsp), %xmm5 movsd 16(%rsp), %xmm5
movsd 24(%rsp), %xmm4 movsd 24(%rsp), %xmm4
movsd 32(%rsp), %xmm3 movsd 32(%rsp), %xmm3
movsd 40(%rsp), %xmm2 movsd 40(%rsp), %xmm2
movsd 48(%rsp), %xmm1 movsd 48(%rsp), %xmm1
movsd 56(%rsp), %xmm0 movsd 56(%rsp), %xmm0
add $64, %rsp add $64, %rsp
# at this point new stack is clean (no intermediate values) # at this point new stack is clean (no intermediate values)
# on stack it look like this # on stack it look like this
# SP -> 0 # SP -> 0
# entry_func # entry_func
# pop 0 as rbp # pop 0 as rbp
popq %rbp popq %rbp
# pop entry func to r10 (this is a caller saved register, it is save for us to use) # pop entry func to r10 (this is a caller saved register, it is save for us to use)
popq %r10 popq %r10
call *%r10 call *%r10
end_func muthread_start_normal 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) # muentry_thread_exit(old_sp: Address)
# %rdi # %rdi
begin_func muentry_thread_exit begin_func muentry_thread_exit
movq %rdi, %rsp movq %rdi, %rsp
popq %r15 popq %r15
popq %r14 popq %r14
popq %r13 popq %r13
popq %r12 popq %r12
popq %rbx popq %rbx
popq %rbp popq %rbp
ret ret
end_func muentry_thread_exit 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) # muentry_throw_exception(obj: Address)
# %rdi # %rdi
begin_func muentry_throw_exception begin_func muentry_throw_exception
# save all callee-saved # save all callee-saved
pushq %rbp pushq %rbp
movq %rsp, %rbp movq %rsp, %rbp
pushq %rbx pushq %rbx
pushq %r12 pushq %r12
pushq %r13 pushq %r13
pushq %r14 pushq %r14
pushq %r15 pushq %r15
# %rsp points to %rbx, pass this as 2nd argument # %rsp points to %rbx, pass this as 2nd argument
movq %rbp, %rsi movq %rbp, %rsi
#if defined (__linux__) jmp_to throw_exception_internal
jmp CNAME(throw_exception_internal@PLT) # won't return
#elif defined (__APPLE__) end_func muentry_throw_exception
jmp CNAME(throw_exception_internal)
#else
#error "Only Linux and OSX are supported. "
#endif
# won't return
# _exception_restore(dest: Address, callee_saved: *const Word, rsp: Address) -> ! # _exception_restore(dest: Address, callee_saved: *const Word, rsp: Address) -> !
# %rdi %rsi %rdx # %rdi %rsi %rdx
# callee_saved: [rbx, rbp, r12, r13, r14, r15] # callee_saved: [rbx, rbp, r12, r13, r14, r15]
begin_func exception_restore begin_func exception_restore
movq 0(%rsi), %rbp movq 0(%rsi), %rbp
movq -8(%rsi),%rbx movq -8(%rsi),%rbx
movq -16(%rsi),%r12 movq -16(%rsi),%r12
movq -24(%rsi),%r13 movq -24(%rsi),%r13
movq -32(%rsi),%r14 movq -32(%rsi),%r14
movq -40(%rsi),%r15 movq -40(%rsi),%r15
movq %rdx, %rsp movq %rdx, %rsp
jmpq *%rdi jmpq *%rdi
end_func exception_restore end_func exception_restore
\ No newline at end of file
...@@ -185,9 +185,9 @@ impl MuStack { ...@@ -185,9 +185,9 @@ impl MuStack {
/// sets up arguments for the stack's entry function, so it is ready to be executed. /// 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 /// 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 /// 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. /// 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 /// those values pushed to the stack
pub fn setup_args(&mut self, vals: Vec<ValueLocation>) { pub fn setup_args(&mut self, vals: Vec<ValueLocation>) {
use utils::Word; 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