Commit c2b9b779 authored by qinsoon's avatar qinsoon

tests use either compile_to_sharedlib or make_boot_image to link

generated code. Now internally Zebu use make_boot_image for
compile_to_sharedlib
parent f2a9fa60
extern crate libloading;
use testutil::get_test_clang_path;
use testutil::exec;
use std::path::Path;
use std::path::PathBuf;
use std::process::Command;
use std::env;
pub fn compile_run_c_test(test_file_path: &'static str) -> PathBuf {
let mut src = Path::new("tests/test_jit").to_path_buf();
src.push(test_file_path);
let output = {
use std::fs;
let temp = Path::new("tests/test_jit/temp");
fs::create_dir_all(temp).unwrap();
let mut ret = temp.to_path_buf();
ret.push(src.file_stem().unwrap());
ret
};
// compile the C test
let mut cc = Command::new(get_test_clang_path());
cc.arg("-std=c99");
cc.arg("-Isrc/vm/api");
let build = match env::var("ZEBU_BUILD") {
Ok(val) => val,
Err(_) => "debug".to_string()
};
cc.arg(format!("-Ltarget/{}", build));
cc.arg("-lmu");
// src
cc.arg(src.as_os_str());
// output
cc.arg("-o");
cc.arg(output.as_os_str());
exec(cc);
// run the executable
let test = Command::new(output.as_os_str());
let test_out = exec(test);
Path::new(&String::from_utf8(test_out.stdout).unwrap()).to_path_buf()
}
...@@ -11,7 +11,6 @@ use std::process::Output; ...@@ -11,7 +11,6 @@ use std::process::Output;
use std::os::unix::process::ExitStatusExt; use std::os::unix::process::ExitStatusExt;
pub mod aot; pub mod aot;
pub mod c_api;
pub fn get_test_clang_path() -> String { pub fn get_test_clang_path() -> String {
use std::env; use std::env;
......
...@@ -80,19 +80,19 @@ impl MuVM { ...@@ -80,19 +80,19 @@ impl MuVM {
use compiler::*; use compiler::*;
use testutil::aot; use testutil::aot;
let compiler = Compiler::new(CompilerPolicy::default(), &self.vm); let funcs : Vec<MuID> = {
let funcs = self.vm.funcs().read().unwrap(); let funcs = self.vm.funcs().read().unwrap();
let mut func_names = vec![]; funcs.keys().map(|x| *x).collect()
// NOTE: this fails because load() API call is not properly implemented yet. };
for (func_id, ref f) in funcs.iter() {
let func = f.read().unwrap(); self.vm.make_boot_image_internal(funcs,
let func_vers = self.vm.func_vers().read().unwrap(); None, None,
let mut func_ver = func_vers.get(&func.cur_ver.unwrap()).unwrap().write().unwrap(); None,
compiler.compile(&mut func_ver); vec![], vec![],
func_names.push(func.name().unwrap()); vec![], vec![],
} extra_srcs,
backend::emit_context(&self.vm); lib_name
aot::link_dylib_with_extra_srcs(func_names, extra_srcs, &lib_name, &self.vm); );
} }
pub fn current_thread_as_mu_thread(&self, threadlocal: CMuCPtr) { pub fn current_thread_as_mu_thread(&self, threadlocal: CMuCPtr) {
......
...@@ -989,15 +989,34 @@ impl <'a> VM { ...@@ -989,15 +989,34 @@ impl <'a> VM {
let mut guard = self.primordial.write().unwrap(); let mut guard = self.primordial.write().unwrap();
*guard = Some(MuPrimordialThread{func_id: func_id, has_const_args: has_const_args, args: args}); *guard = Some(MuPrimordialThread{func_id: func_id, has_const_args: has_const_args, args: args});
} }
pub fn make_boot_image(&self,
whitelist: Vec<MuID>,
primordial_func: Option<&APIHandle>, primordial_stack: Option<&APIHandle>,
primordial_threadlocal: Option<&APIHandle>,
sym_fields: Vec<&APIHandle>, sym_strings: Vec<String>,
reloc_fields: Vec<&APIHandle>, reloc_strings: Vec<String>,
output_file: String) {
self.make_boot_image_internal(
whitelist,
primordial_func, primordial_stack,
primordial_threadlocal,
sym_fields, sym_strings,
reloc_fields, reloc_strings,
vec![],
output_file
)
}
#[allow(unused_variables)] #[allow(unused_variables)]
pub fn make_boot_image(&self, pub fn make_boot_image_internal(&self,
whitelist: Vec<MuID>, whitelist: Vec<MuID>,
primordial_func: Option<&APIHandle>, primordial_stack: Option<&APIHandle>, primordial_func: Option<&APIHandle>, primordial_stack: Option<&APIHandle>,
primordial_threadlocal: Option<&APIHandle>, primordial_threadlocal: Option<&APIHandle>,
sym_fields: Vec<&APIHandle>, sym_strings: Vec<String>, sym_fields: Vec<&APIHandle>, sym_strings: Vec<String>,
reloc_fields: Vec<&APIHandle>, reloc_strings: Vec<String>, reloc_fields: Vec<&APIHandle>, reloc_strings: Vec<String>,
output_file: String) { extra_sources_to_link: Vec<String>,
output_file: String) {
trace!("Making boot image..."); trace!("Making boot image...");
let whitelist_funcs = { let whitelist_funcs = {
...@@ -1036,22 +1055,20 @@ impl <'a> VM { ...@@ -1036,22 +1055,20 @@ impl <'a> VM {
// make sure only one of primordial_func or primoridial_stack is set // make sure only one of primordial_func or primoridial_stack is set
let has_primordial_func = primordial_func.is_some(); let has_primordial_func = primordial_func.is_some();
let has_primordial_stack = primordial_stack.is_some(); let has_primordial_stack = primordial_stack.is_some();
assert!(
// do not have promordial stack/func
(!has_primordial_func && !has_primordial_stack)
// have either stack or func
|| ((has_primordial_func && !has_primordial_stack) || (!has_primordial_func && has_primordial_stack))
);
// we assume client will start with a function (instead of a stack) // we assume client will start with a function (instead of a stack)
if has_primordial_stack { if has_primordial_stack {
panic!("Zebu doesnt support creating primordial thread through a stack, name a entry function instead") panic!("Zebu doesnt support creating primordial thread through a stack, name a entry function instead")
} else { } else {
// extract func id if has_primordial_func {
let func_id = primordial_func.unwrap().v.as_funcref(); // extract func id
let func_id = primordial_func.unwrap().v.as_funcref();
// make primordial thread in vm
self.make_primordial_thread(func_id, false, vec![]); // do not pass const args, use argc/argv // make primordial thread in vm
self.make_primordial_thread(func_id, false, vec![]); // do not pass const args, use argc/argv
} else {
warn!("no entry function is passed");
}
// deal with relocation symbols // deal with relocation symbols
assert_eq!(sym_fields.len(), sym_strings.len()); assert_eq!(sym_fields.len(), sym_strings.len());
...@@ -1089,12 +1106,12 @@ impl <'a> VM { ...@@ -1089,12 +1106,12 @@ impl <'a> VM {
backend::emit_context_with_reloc(self, symbols, fields); backend::emit_context_with_reloc(self, symbols, fields);
// link // link
self.link_boot_image(whitelist_funcs, output_file); self.link_boot_image(whitelist_funcs, extra_sources_to_link, output_file);
} }
} }
#[cfg(feature = "aot")] #[cfg(feature = "aot")]
fn link_boot_image(&self, funcs: Vec<MuID>, output_file: String) { fn link_boot_image(&self, funcs: Vec<MuID>, extra_srcs: Vec<String>, output_file: String) {
use testutil; use testutil;
trace!("Linking boot image..."); trace!("Linking boot image...");
...@@ -1105,12 +1122,14 @@ impl <'a> VM { ...@@ -1105,12 +1122,14 @@ impl <'a> VM {
}; };
trace!("functions: {:?}", func_names); trace!("functions: {:?}", func_names);
trace!("extern sources: {:?}", extra_srcs);
trace!("output : {}", output_file); trace!("output : {}", output_file);
if output_file.ends_with("dylib") || output_file.ends_with("so") { if output_file.ends_with("dylib") || output_file.ends_with("so") {
// compile as dynamic library // compile as dynamic library
testutil::aot::link_dylib(func_names, &output_file, self); testutil::aot::link_dylib_with_extra_srcs(func_names, extra_srcs, &output_file, self);
} else { } else {
assert!(extra_srcs.len() == 0, "trying to create an executable with linking extern sources, unimplemented");
// compile as executable // compile as executable
testutil::aot::link_primordial(func_names, &output_file, self); testutil::aot::link_primordial(func_names, &output_file, self);
} }
......
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