Commit 8da9f1ed authored by qinsoon's avatar qinsoon

simple throw catch works fine

internal id and machine id do not persist during serialization
and restoration. Currently I use fixed ID for machine registers.
But internal id is still generated, this might be a problem in
the future.
parent 102a2e30
......@@ -40,6 +40,11 @@ pub const INTERNAL_ID_START: usize = 101;
pub const INTERNAL_ID_END : usize = 200;
pub const USER_ID_START : usize = 201;
#[deprecated]
#[allow(dead_code)]
/// it could happen that one same machine register get different IDs
/// during serialization and restoring
/// currently I hand-write fixed ID for each machine register
pub fn new_machine_id() -> MuID {
let ret = MACHINE_ID.fetch_add(1, Ordering::SeqCst);
if ret >= MACHINE_ID_END {
......
......@@ -19,26 +19,24 @@ use compiler::backend::RegGroup;
use std::collections::HashMap;
macro_rules! GPR {
($name: expr) => {
($id:expr, $name: expr) => {
{
let id = new_machine_id();
P(Value {
hdr: MuEntityHeader::named(id, $name.to_string()),
hdr: MuEntityHeader::named($id, $name.to_string()),
ty: UINT64_TYPE.clone(),
v: Value_::SSAVar(id)
v: Value_::SSAVar($id)
})
}
};
}
macro_rules! FPR {
($name: expr) => {
($id:expr, $name: expr) => {
{
let id = new_machine_id();
P(Value {
hdr: MuEntityHeader::named(id, $name.to_string()),
hdr: MuEntityHeader::named($id, $name.to_string()),
ty: DOUBLE_TYPE.clone(),
v: Value_::SSAVar(id)
v: Value_::SSAVar($id)
})
}
};
......@@ -46,24 +44,24 @@ macro_rules! FPR {
// put into several segments to avoid 'recursion limit reached' error
lazy_static! {
pub static ref RAX : P<Value> = GPR!("rax");
pub static ref RCX : P<Value> = GPR!("rcx");
pub static ref RDX : P<Value> = GPR!("rdx");
pub static ref RBX : P<Value> = GPR!("rbx");
pub static ref RSP : P<Value> = GPR!("rsp");
pub static ref RBP : P<Value> = GPR!("rbp");
pub static ref RSI : P<Value> = GPR!("rsi");
pub static ref RDI : P<Value> = GPR!("rdi");
pub static ref R8 : P<Value> = GPR!("r8");
pub static ref R9 : P<Value> = GPR!("r9");
pub static ref R10 : P<Value> = GPR!("r10");
pub static ref R11 : P<Value> = GPR!("r11");
pub static ref R12 : P<Value> = GPR!("r12");
pub static ref R13 : P<Value> = GPR!("r13");
pub static ref R14 : P<Value> = GPR!("r14");
pub static ref R15 : P<Value> = GPR!("r15");
pub static ref RAX : P<Value> = GPR!(0, "rax");
pub static ref RCX : P<Value> = GPR!(1, "rcx");
pub static ref RDX : P<Value> = GPR!(2, "rdx");
pub static ref RBX : P<Value> = GPR!(3, "rbx");
pub static ref RSP : P<Value> = GPR!(4, "rsp");
pub static ref RBP : P<Value> = GPR!(5, "rbp");
pub static ref RSI : P<Value> = GPR!(6, "rsi");
pub static ref RDI : P<Value> = GPR!(7, "rdi");
pub static ref R8 : P<Value> = GPR!(8, "r8");
pub static ref R9 : P<Value> = GPR!(9, "r9");
pub static ref R10 : P<Value> = GPR!(10,"r10");
pub static ref R11 : P<Value> = GPR!(11,"r11");
pub static ref R12 : P<Value> = GPR!(12,"r12");
pub static ref R13 : P<Value> = GPR!(13,"r13");
pub static ref R14 : P<Value> = GPR!(14,"r14");
pub static ref R15 : P<Value> = GPR!(15,"r15");
pub static ref RIP : P<Value> = GPR!("rip");
pub static ref RIP : P<Value> = GPR!(32,"rip");
pub static ref RETURN_GPRs : [P<Value>; 2] = [
RAX.clone(),
......@@ -109,22 +107,22 @@ lazy_static! {
}
lazy_static!{
pub static ref XMM0 : P<Value> = FPR!("xmm0");
pub static ref XMM1 : P<Value> = FPR!("xmm1");
pub static ref XMM2 : P<Value> = FPR!("xmm2");
pub static ref XMM3 : P<Value> = FPR!("xmm3");
pub static ref XMM4 : P<Value> = FPR!("xmm4");
pub static ref XMM5 : P<Value> = FPR!("xmm5");
pub static ref XMM6 : P<Value> = FPR!("xmm6");
pub static ref XMM7 : P<Value> = FPR!("xmm7");
pub static ref XMM8 : P<Value> = FPR!("xmm8");
pub static ref XMM9 : P<Value> = FPR!("xmm9");
pub static ref XMM10 : P<Value> = FPR!("xmm10");
pub static ref XMM11 : P<Value> = FPR!("xmm11");
pub static ref XMM12 : P<Value> = FPR!("xmm12");
pub static ref XMM13 : P<Value> = FPR!("xmm13");
pub static ref XMM14 : P<Value> = FPR!("xmm14");
pub static ref XMM15 : P<Value> = FPR!("xmm15");
pub static ref XMM0 : P<Value> = FPR!(16,"xmm0");
pub static ref XMM1 : P<Value> = FPR!(17,"xmm1");
pub static ref XMM2 : P<Value> = FPR!(18,"xmm2");
pub static ref XMM3 : P<Value> = FPR!(19,"xmm3");
pub static ref XMM4 : P<Value> = FPR!(20,"xmm4");
pub static ref XMM5 : P<Value> = FPR!(21,"xmm5");
pub static ref XMM6 : P<Value> = FPR!(22,"xmm6");
pub static ref XMM7 : P<Value> = FPR!(23,"xmm7");
pub static ref XMM8 : P<Value> = FPR!(24,"xmm8");
pub static ref XMM9 : P<Value> = FPR!(25,"xmm9");
pub static ref XMM10 : P<Value> = FPR!(26,"xmm10");
pub static ref XMM11 : P<Value> = FPR!(27,"xmm11");
pub static ref XMM12 : P<Value> = FPR!(28,"xmm12");
pub static ref XMM13 : P<Value> = FPR!(29,"xmm13");
pub static ref XMM14 : P<Value> = FPR!(30,"xmm14");
pub static ref XMM15 : P<Value> = FPR!(31,"xmm15");
pub static ref RETURN_FPRs : [P<Value>; 2] = [
XMM0.clone(),
......
......@@ -54,6 +54,10 @@ impl Frame {
}
}
pub fn cur_offset(&self) -> isize {
self.cur_offset
}
pub fn alloc_slot_for_callee_saved_reg(&mut self, reg: P<Value>, vm: &VM) -> P<Value> {
let slot = self.alloc_slot(&reg, vm);
slot.make_memory_op(reg.ty.clone(), vm)
......
......@@ -13,6 +13,7 @@ use std::collections::HashMap;
use std::fmt;
#[no_mangle]
#[allow(unreachable_code)]
pub extern fn muentry_throw_exception(exception_obj: Address) {
trace!("throwing exception: {}", exception_obj);
......@@ -72,12 +73,20 @@ pub extern fn muentry_throw_exception(exception_obj: Address) {
// update callee saved register location
for reg in x86_64::CALLEE_SAVED_GPRs.iter() {
let reg_id = reg.id();
trace!("update callee saved register {}", reg_id);
if frame.allocated.contains_key(&reg_id) {
let offset_from_rbp = frame.allocated.get(&reg_id).unwrap().offset;
let reg_restore_addr = cursor.rbp.offset(offset_from_rbp);
trace!("update callee saved register {} with loc 0x{:x}", reg_id, reg_restore_addr);
cursor.callee_saved_locs.insert(reg_id, reg_restore_addr);
} else {
// rbp won't find a location
if reg_id == x86_64::RBP.id() {
} else {
warn!("failed to find an entry for it in current frame");
}
}
}
......@@ -94,7 +103,33 @@ pub extern fn muentry_throw_exception(exception_obj: Address) {
let dest_addr = dest.to_address();
// restore callee saved register and jump to dest_addr
unimplemented!()
// prepare a plain array [rbx, rbp, r12, r13, r14, r15]
macro_rules! unpack_callee_saved_from_cursor {
($reg: expr) => {
match cursor.callee_saved_locs.get(&$reg.id()) {
Some(addr) => unsafe {addr.load::<Word>()},
None => {
warn!("no {} value was saved along unwinding, please check", $reg.name().unwrap());
0
}
}
}
};
let rbx = unpack_callee_saved_from_cursor!(x86_64::RBX);
let r12 = unpack_callee_saved_from_cursor!(x86_64::R12);
let r13 = unpack_callee_saved_from_cursor!(x86_64::R13);
let r14 = unpack_callee_saved_from_cursor!(x86_64::R14);
let r15 = unpack_callee_saved_from_cursor!(x86_64::R15);
let rbp = cursor.rbp.as_usize() as Word;
let array = vec![rbx, rbp, r12, r13, r14, r15];
let rsp = cursor.rbp.offset(frame.cur_offset());
unsafe {thread::exception_restore(dest_addr, array.as_ptr(), rsp)};
unreachable!()
}
}
trace!("didnt find a catch block");
......
......@@ -67,3 +67,18 @@ _muentry_swap_back_to_native_stack:
_get_current_frame_rbp:
movq %rbp, %rax
ret
# _exception_restore(dest: Address, callee_saved: *const Word, rsp: Address) -> !
# %rdi %rsi %rdx
# callee_saved: [rbx, rbp, r12, r13, r14, r15]
.globl _exception_restore
_exception_restore:
movq 0(%rsi), %rbx
movq 8(%rsi), %rbp
movq 16(%rsi),%r12
movq 24(%rsi),%r13
movq 32(%rsi),%r14
movq 40(%rsi),%r15
movq %rdx, %rsp
jmpq *%rdi
......@@ -10,6 +10,7 @@ use runtime::mm;
use utils::ByteSize;
use utils::Address;
use utils::Word;
use utils::mem::memmap;
use utils::mem::memsec;
......@@ -248,6 +249,7 @@ extern "C" {
fn swap_to_mu_stack(new_sp: Address, entry: Address, old_sp_loc: Address);
fn muentry_swap_back_to_native_stack(sp_loc: Address);
pub fn get_current_frame_rbp() -> Address;
pub fn exception_restore(dest: Address, callee_saved: *const Word, rsp: Address) -> !;
}
impl MuThread {
......
......@@ -22,6 +22,11 @@ use std::sync::RwLock;
use std::sync::atomic::{AtomicUsize, AtomicBool, ATOMIC_BOOL_INIT, ATOMIC_USIZE_INIT, Ordering};
use std::thread::JoinHandle;
// FIXME:
// besides fields in VM, there are some 'globals' we need to persist
// such as STRUCT_TAG_MAP
// possibly INTERNAL_ID in ir.rs, internal types, etc
pub struct VM {
// serialize
// 0
......
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