mod.rs 3.64 KB
Newer Older
1
pub mod mm;
qinsoon's avatar
qinsoon committed
2
pub mod thread;
3
pub mod entrypoints;
qinsoon's avatar
qinsoon committed
4

5 6
pub use runtime::mm::common::Address;
pub use runtime::mm::common::ObjectReference;
7

8 9
use log;
use simple_logger;
10
use utils;
11 12 13 14
use ast::ir;
use ast::ptr::*;
use ast::types::MuType_;
use ast::types::MuType;
15
use ast::ir::*;
16
use vm::VM;
17 18 19
use compiler::backend::Word;
use compiler::backend::RegGroup;

20 21 22
use std::os::raw::c_char;
use std::os::raw::c_void;
use std::ffi::CString;
23 24 25
use std::ffi::CStr;

use std::sync::Arc;
26

27 28 29 30 31 32
lazy_static! {
    pub static ref ADDRESS_TYPE : P<MuType> = P(
        MuType::new(ir::new_internal_id(), MuType_::int(64))
    );
}

33 34 35
// consider using libloading crate instead of the raw c functions for dynalic libraries
// however i am not sure if libloading can load symbols from current process (not from an actual dylib)
// so here i use dlopen/dlsym from C
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
#[link(name="dl")]
extern "C" {
    fn dlopen(filename: *const c_char, flags: isize) -> *const c_void;
    fn dlsym(handle: *const c_void, symbol: *const c_char) -> *const c_void;
}

pub fn resolve_symbol(symbol: String) -> Address {
    use std::ptr;
    
    let rtld_default = unsafe {dlopen(ptr::null(), 0)};
    let ret = unsafe {dlsym(rtld_default, CString::new(symbol.clone()).unwrap().as_ptr())};
    
    if ret == 0 as *const c_void {
        panic!("cannot find symbol {}", symbol);
    }
    
    Address::from_ptr(ret)
}

55
#[derive(Clone, Debug)]
56 57 58 59 60 61 62 63 64 65 66 67 68 69
pub enum ValueLocation {
    Register(RegGroup, MuID),
    Direct(RegGroup, Address),
    Indirect(RegGroup, Address),
    Constant(RegGroup, Word),
    
    Relocatable(RegGroup, MuName)
}

impl ValueLocation {
    pub fn load_value(&self) -> (RegGroup, Word) {
        match self {
            &ValueLocation::Register(_, _)
            | &ValueLocation::Direct(_, _)
70 71 72 73 74
            | &ValueLocation::Indirect(_, _) => unimplemented!(),
            
            &ValueLocation::Constant(group, word) => {
                (group, word)
            }
75 76 77
            &ValueLocation::Relocatable(_, _) => panic!("expect a runtime value")
        }
    }
qinsoon's avatar
qinsoon committed
78
    
79
    #[allow(unused_variables)]
qinsoon's avatar
qinsoon committed
80
    pub fn from_constant(c: Constant) -> ValueLocation {
81 82 83 84 85 86 87
        match c {
            Constant::Int(int_val) => ValueLocation::Constant(RegGroup::GPR, utils::mem::u64_to_raw(int_val)),
            Constant::Float(f32_val) => ValueLocation::Constant(RegGroup::FPR, utils::mem::f32_to_raw(f32_val)),
            Constant::Double(f64_val) => ValueLocation::Constant(RegGroup::FPR, utils::mem::f64_to_raw(f64_val)),
            
            _ => unimplemented!()
        }
qinsoon's avatar
qinsoon committed
88
    }
89 90
}

91 92
pub const PRIMORDIAL_ENTRY : &'static str = "src/runtime/main.c";

93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
#[no_mangle]
pub extern fn mu_trace_level_log() {
    simple_logger::init_with_level(log::LogLevel::Trace).ok();
}

#[no_mangle]
pub extern fn mu_main(serialized_vm : *const c_char) {      
    debug!("mu_main() started...");
    
    let str_vm = unsafe{CStr::from_ptr(serialized_vm)}.to_str().unwrap();
    
    let vm : Arc<VM> = Arc::new(VM::resume_vm(str_vm));
    
    let primordial = vm.primordial.read().unwrap();
    if primordial.is_none() {
        panic!("no primordial thread/stack/function. Client should provide an entry point");
    } else {
        let primordial = primordial.as_ref().unwrap();
        
        // create mu stack
        let stack = vm.new_stack(primordial.func_id);
        
        let args : Vec<ValueLocation> = primordial.args.iter().map(|arg| ValueLocation::from_constant(arg.clone())).collect();
        
        // FIXME: currently assumes no user defined thread local
        // will need to fix this after we can serialize heap object
        let thread = vm.new_thread_normal(stack, unsafe{Address::zero()}, args);
        
        thread.join().unwrap();
    }
qinsoon's avatar
qinsoon committed
123
}