Commit 071cf7e1 authored by qinsoon's avatar qinsoon

[wip] going to work on catch block (exception arg)

parent 214d799f
......@@ -661,23 +661,23 @@ impl CodeGenerator for ASMCodeGen {
self.add_asm_symbolic(directive_globl(func_symbol.clone()));
self.add_asm_symbolic(format!("{}:", func_symbol.clone()));
ValueLocation::Relocatable(RegGroup::GPR, func_symbol)
ValueLocation::Relocatable(RegGroup::GPR, func_name)
}
fn finish_code(&mut self, func_name: MuName) -> (Box<MachineCode + Sync + Send>, ValueLocation) {
let func_end_symbol = {
let mut symbol = symbol(func_name.clone());
let func_end = {
let mut symbol = func_name.clone();
symbol.push_str("_end");
symbol
};
self.add_asm_symbolic(directive_globl(func_end_symbol.clone()));
self.add_asm_symbolic(format!("{}:", func_end_symbol.clone()));
self.add_asm_symbolic(directive_globl(symbol(func_end.clone())));
self.add_asm_symbolic(format!("{}:", symbol(func_end.clone())));
self.control_flow_analysis();
(
self.cur.take().unwrap(),
ValueLocation::Relocatable(RegGroup::GPR, func_end_symbol)
ValueLocation::Relocatable(RegGroup::GPR, func_end)
)
}
......@@ -710,13 +710,13 @@ impl CodeGenerator for ASMCodeGen {
}
fn start_exception_block(&mut self, block_name: MuName) -> ValueLocation {
let block_symbol = symbol(self.asm_block_label(block_name.clone()));
self.add_asm_symbolic(directive_globl(block_symbol.clone()));
self.add_asm_symbolic(format!("{}:", block_symbol.clone()));
let block = self.asm_block_label(block_name.clone());
self.add_asm_symbolic(directive_globl(symbol(block.clone())));
self.add_asm_symbolic(format!("{}:", symbol(block.clone())));
self.start_block(block_name);
ValueLocation::Relocatable(RegGroup::GPR, block_symbol)
ValueLocation::Relocatable(RegGroup::GPR, block)
}
fn end_block(&mut self, block_name: MuName) {
......@@ -1155,14 +1155,14 @@ impl CodeGenerator for ASMCodeGen {
fn emit_call_near_rel32(&mut self, callsite: String, func: MuName) -> ValueLocation {
trace!("emit: call {}", func);
let callsite_symbol = symbol(callsite);
let callsite_symbol = symbol(callsite.clone());
self.add_asm_symbolic(directive_globl(callsite_symbol.clone()));
self.add_asm_symbolic(format!("{}:", callsite_symbol.clone()));
let asm = format!("call {}", symbol(func));
self.add_asm_call(asm);
ValueLocation::Relocatable(RegGroup::GPR, callsite_symbol)
ValueLocation::Relocatable(RegGroup::GPR, callsite)
}
fn emit_call_near_r64(&mut self, callsite: String, func: &P<Value>) -> ValueLocation {
......
......@@ -3,6 +3,7 @@ use ast::ptr::*;
use ast::types::*;
use runtime::ValueLocation;
use std::fmt;
use std::collections::HashMap;
use utils::POINTER_SIZE;
use vm::VM;
......@@ -28,6 +29,21 @@ pub struct Frame {
pub exception_callsites: HashMap<ValueLocation, ValueLocation>
}
impl fmt::Display for Frame {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
writeln!(f, "Frame for FuncVer {} {{", self.func_ver_id).unwrap();
writeln!(f, " allocated slots:").unwrap();
for slot in self.allocated.values() {
writeln!(f, " {}", slot).unwrap();
}
writeln!(f, " exception callsites:").unwrap();
for (callsite, dest) in self.exception_callsites.iter() {
writeln!(f, " callsite: {} -> {}", callsite, dest).unwrap()
}
writeln!(f, "}}")
}
}
impl Frame {
pub fn new(func_ver_id: MuID) -> Frame {
Frame {
......@@ -49,6 +65,7 @@ impl Frame {
}
pub fn add_exception_callsite(&mut self, callsite: ValueLocation, dest: ValueLocation) {
trace!("add exception callsite: {} to dest {}", callsite, dest);
self.exception_callsites.insert(callsite, dest);
}
......@@ -72,6 +89,12 @@ pub struct FrameSlot {
pub value: P<Value>
}
impl fmt::Display for FrameSlot {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}(RBP): {}", self.offset, self.value)
}
}
impl FrameSlot {
#[cfg(target_arch = "x86_64")]
pub fn make_memory_op(&self, ty: P<MuType>, vm: &VM) -> P<Value> {
......
......@@ -9,6 +9,7 @@ use runtime::thread;
use std::sync::RwLock;
use std::sync::RwLockReadGuard;
use std::collections::HashMap;
use std::fmt;
#[no_mangle]
pub extern fn muentry_throw_exception(exception_obj: Address) {
......@@ -22,11 +23,14 @@ pub extern fn muentry_throw_exception(exception_obj: Address) {
// rbp of current frame (mu_throw_exception(), Rust frame)
let rust_frame_rbp = unsafe {thread::get_current_frame_rbp()};
trace!("current frame RBP: 0x{:x}", rust_frame_rbp);
let rust_frame_return_addr = unsafe {rust_frame_rbp.plus(POINTER_SIZE).load::<Address>()};
trace!("return address : 0x{:x} - throw instruction", rust_frame_return_addr);
// the return address is within throwing frame
let throw_frame_callsite = rust_frame_return_addr;
let throw_func_id = find_func_for_address(&cf_lock, throw_frame_callsite);
let (throw_func, throw_fv) = find_func_for_address(&cf_lock, throw_frame_callsite);
trace!("throwing fucntion: {}", throw_func);
// skip to previous frame
// this is the frame that throws the exception
......@@ -36,28 +40,27 @@ pub extern fn muentry_throw_exception(exception_obj: Address) {
let mut cursor = FrameCursor {
rbp: rbp,
return_addr: unsafe {rbp.plus(POINTER_SIZE).load::<Address>()},
func_id: throw_func_id,
func_id: throw_func,
func_ver_id: throw_fv,
callee_saved_locs: HashMap::new()
};
trace!("cursor at first Mu frame: {}", cursor);
let mut callsite = rust_frame_return_addr;
trace!("Stack Unwinding starts");
loop {
trace!("frame cursor: {}", cursor);
// get return address (the slot above RBP slot)
// let return_addr = unsafe {rbp.plus(POINTER_SIZE).load::<Address>()};
// check if return_addr is valid
// FIXME: should use a sentinel value here
if cursor.return_addr.is_zero() {
panic!("cannot find exception catch block, throws by {}", throw_func_id);
}
let callsite = cursor.return_addr;
let rwlock_cf = match cf_lock.get(&cursor.func_id) {
let rwlock_cf = match cf_lock.get(&cursor.func_ver_id) {
Some(ret) => ret,
None => panic!("cannot find compiled func with func_id {}, possibly didnt find the right frame for return address", cursor.func_id)
};
let rwlock_cf = rwlock_cf.read().unwrap();
let ref frame = rwlock_cf.frame;
trace!("frame info: {}", frame);
// update callee saved register location
for reg in x86_64::CALLEE_SAVED_GPRs.iter() {
......@@ -66,26 +69,32 @@ pub extern fn muentry_throw_exception(exception_obj: Address) {
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);
}
}
cursor.to_previous_frame(&cf_lock);
// find exception block - comparing callsite with frame info
trace!("checking catch block: looking for callsite 0x{:x}", callsite);
let ref exception_callsites = frame.exception_callsites;
for (possible_callsite, dest) in exception_callsites {
let possible_callsite_addr = possible_callsite.to_address();
if callsite == possible_callsite_addr {
trace!("found catch block at {}", dest);
// found an exception block
let dest_addr = dest.to_address();
// restore callee saved register and jump to dest_addr
unimplemented!()
}
}
trace!("didnt find a catch block");
// keep unwinding
callsite = cursor.return_addr;
cursor.to_previous_frame(&cf_lock);
trace!("cursor unwinds to previous frame: {}", cursor);
}
}
......@@ -93,21 +102,55 @@ struct FrameCursor {
rbp: Address,
return_addr: Address,
func_id: MuID,
func_ver_id: MuID,
callee_saved_locs: HashMap<MuID, Address>
}
impl fmt::Display for FrameCursor {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
writeln!(f, "FrameCursor{{").unwrap();
writeln!(f, " rbp=0x{:x}, return_addr=0x{:x}, func_id={}, func_version_id={}", self.rbp, self.return_addr, self.func_id, self.func_ver_id).unwrap();
writeln!(f, " callee_saved:").unwrap();
for (reg, addr) in self.callee_saved_locs.iter() {
writeln!(f, " #{} at 0x{:x}", reg, addr).unwrap()
}
writeln!(f, "}}")
}
}
impl FrameCursor {
fn to_previous_frame(&mut self, cf: &RwLockReadGuard<HashMap<MuID, RwLock<CompiledFunction>>>) {
// check if return_addr is valid
// FIXME: should use a sentinel value here
if self.return_addr.is_zero() {
panic!("cannot go to previous frame (return address is zero)");
}
let previous_rbp = unsafe {self.rbp.load::<Address>()};
let previous_return_addr = unsafe {previous_rbp.plus(POINTER_SIZE).load::<Address>()};
let previous_func_id = find_func_for_address(cf, self.return_addr);
let (previous_func, previous_fv_id) = find_func_for_address(cf, self.return_addr);
self.rbp = previous_rbp;
self.return_addr = previous_return_addr;
self.func_id = previous_func_id;
self.func_id = previous_func;
self.func_ver_id = previous_fv_id;
}
}
fn find_func_for_address (cf: &RwLockReadGuard<HashMap<MuID, RwLock<CompiledFunction>>>, pc_addr: Address) -> MuID {
unimplemented!()
fn find_func_for_address (cf: &RwLockReadGuard<HashMap<MuID, RwLock<CompiledFunction>>>, pc_addr: Address) -> (MuID, MuID) {
trace!("trying to find FuncVersion for address 0x{:x}", pc_addr);
for (id, func) in cf.iter() {
let func = func.read().unwrap();
let start = func.start.to_address();
let end = func.end.to_address();
trace!("CompiledFunction: func_id={}, fv_id={}, start=0x{:x}, end=0x{:x}", func.func_id, func.func_ver_id, start, end);
if pc_addr >= start && pc_addr <= end {
trace!("Found CompiledFunction: func_id={}, fv_id={}", func.func_id, func.func_ver_id);
return (func.func_id, func.func_ver_id);
}
}
panic!("cannot find compiled function for pc 0x{:x}");
}
\ No newline at end of file
......@@ -7,6 +7,7 @@ use compiler::backend::Word;
use compiler::backend::RegGroup;
use utils::Address;
use std::fmt;
use std::os::raw::c_char;
use std::os::raw::c_void;
use std::ffi::CString;
......@@ -55,6 +56,18 @@ pub enum ValueLocation {
Indirect(RegGroup, Address), // 4
}
impl fmt::Display for ValueLocation {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&ValueLocation::Register(_, id) => write!(f, "VL_Reg: {}", id),
&ValueLocation::Constant(_, val) => write!(f, "VL_Const: {}", val),
&ValueLocation::Relocatable(_, ref name) => write!(f, "VL_Reloc: {}", name),
&ValueLocation::Direct(_, addr) => write!(f, "VL_Direct: 0x{:x}", addr),
&ValueLocation::Indirect(_, addr) => write!(f, "VL_Indirect: 0x{:x}", addr)
}
}
}
impl Encodable for ValueLocation {
fn encode<S: Encoder> (&self, s: &mut S) -> Result<(), S::Error> {
s.emit_enum("ValueLocation", |s| {
......
......@@ -157,6 +157,9 @@ fn create_catch_exception_func (vm: &VM) {
// %blk_exn_cont() %EXN:
let mut blk_exn_cont = Block::new(blk_exn_cont_id);
vm.set_name(blk_exn_cont.as_entity(), Mu("blk_exn_cont"));
let type_ref_int64 = vm.get_type(vm.id_of("ref_int64"));
let blk_exn_cont_exception_arg = func_ver.new_ssa(vm.next_id(), type_ref_int64.clone());
vm.set_name(blk_exn_cont_exception_arg.as_entity(), Mu("blk_0_exception_arg"));
let blk_exn_cont_thread_exit = func_ver.new_inst(vm.next_id(), Instruction {
value: None,
ops: RwLock::new(vec![]),
......@@ -164,7 +167,7 @@ fn create_catch_exception_func (vm: &VM) {
});
blk_exn_cont.content = Some(BlockContent {
args: vec![],
exn_arg: None,
exn_arg: Some(blk_exn_cont_exception_arg.clone_value()),
body: vec![blk_exn_cont_thread_exit],
keepalives: None
});
......
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