Commit a9b0e905 authored by John Zhang's avatar John Zhang

refactor: put `aot` module and `compile_sharedlib` function under…

refactor: put `aot` module and `compile_sharedlib` function under `mu::vm::testutil` module. Also updated some function calls based on updates in master branch
parent 23dd5e47
......@@ -14,3 +14,4 @@ pub extern crate utils;
pub mod vm;
pub mod compiler;
pub mod runtime;
pub mod testutil;
extern crate log;
extern crate simple_logger;
extern crate libloading as ll;
use compiler::*;
use ast::ir::*;
use vm::*;
use std::sync::Arc;
pub mod aot {
use ast::ir::MuName;
use runtime;
use compiler::backend;
use std::path::PathBuf;
use std::process::Command;
use std::process::Output;
const CC : &'static str = "clang";
fn exec (mut cmd: Command) -> Output {
println!("executing: {:?}", cmd);
let output = cmd.output().expect("failed to execute");
println!("---out---");
println!("{}", String::from_utf8_lossy(&output.stdout));
println!("---err---");
println!("{}", String::from_utf8_lossy(&output.stderr));
output
}
fn link_executable_internal (files: Vec<PathBuf>, out: PathBuf) -> PathBuf {
let mut gcc = Command::new(CC);
for file in files {
println!("link with {:?}", file.as_path());
gcc.arg(file.as_path());
}
println!("output as {:?}", out.as_path());
gcc.arg("-o");
gcc.arg(out.as_os_str());
assert!(exec(gcc).status.success());
out
}
fn link_dylib_internal (files: Vec<PathBuf>, out: PathBuf) -> PathBuf {
let mut object_files : Vec<PathBuf> = vec![];
for file in files {
let mut gcc = Command::new(CC);
gcc.arg("-c");
gcc.arg("-fpic");
let mut out = file.clone();
out.set_extension("o");
gcc.arg(file.as_os_str());
gcc.arg("-o");
gcc.arg(out.as_os_str());
object_files.push(out);
exec(gcc);
}
let mut gcc = Command::new(CC);
gcc.arg("-shared");
gcc.arg("-Wl");
gcc.arg("-undefined");
gcc.arg("dynamic_lookup");
for obj in object_files {
gcc.arg(obj.as_os_str());
}
gcc.arg("-o");
gcc.arg(out.as_os_str());
exec(gcc);
out
}
fn get_path_for_mu_func (f: MuName) -> PathBuf {
let mut ret = PathBuf::from(backend::AOT_EMIT_DIR);
ret.push(f);
ret.set_extension("s");
ret
}
fn get_path_for_mu_context () -> PathBuf {
let mut ret = PathBuf::from(backend::AOT_EMIT_DIR);
ret.push(backend::AOT_EMIT_CONTEXT_FILE);
ret
}
pub fn link_primordial (funcs: Vec<MuName>, out: &str) -> PathBuf {
let emit_dir = PathBuf::from(backend::AOT_EMIT_DIR);
let files : Vec<PathBuf> = {
use std::fs;
let mut ret = vec![];
// all interested mu funcs
for func in funcs {
ret.push(get_path_for_mu_func(func));
}
// mu context
ret.push(get_path_for_mu_context());
// copy primoridal entry
let source = PathBuf::from(runtime::PRIMORDIAL_ENTRY);
let mut dest = PathBuf::from(backend::AOT_EMIT_DIR);
dest.push("main.c");
fs::copy(source.as_path(), dest.as_path()).unwrap();
// include the primordial C main
ret.push(dest);
// include mu static lib
let libmu = PathBuf::from("target/debug/libmu.a");
ret.push(libmu);
ret
};
let mut out_path = emit_dir.clone();
out_path.push(out);
link_executable_internal(files, out_path)
}
pub fn execute(executable: PathBuf) {
let run = Command::new(executable.as_os_str());
assert!(exec(run).status.success());
}
pub fn link_dylib (funcs: Vec<MuName>, out: &str) -> PathBuf {
let files = {
let mut ret = vec![];
for func in funcs {
ret.push(get_path_for_mu_func(func));
}
ret.push(get_path_for_mu_context());
ret
};
let mut out_path = PathBuf::from(backend::AOT_EMIT_DIR);
out_path.push(out);
link_dylib_internal(files, out_path)
}
}
pub fn compile_fnc<'a>(fnc_name: &'static str, build_fnc: &'a Fn() -> VM) -> ll::Library {
simple_logger::init_with_level(log::LogLevel::Trace).ok();
let vm = Arc::new(build_fnc());
let compiler = Compiler::new(CompilerPolicy::default(), vm.clone());
let func_id = vm.id_of(fnc_name);
{
let funcs = vm.funcs().read().unwrap();
let func = funcs.get(&func_id).unwrap().read().unwrap();
let func_vers = vm.func_vers().read().unwrap();
let mut func_ver = func_vers.get(&func.cur_ver.unwrap()).unwrap().write().unwrap();
compiler.compile(&mut func_ver);
}
backend::emit_context(&vm);
let libname = &format!("lib{}.dylib", fnc_name);
let dylib = aot::link_dylib(vec![Mu(fnc_name)], libname);
ll::Library::new(dylib.as_os_str()).unwrap()
}
......@@ -29,192 +29,3 @@ mod common {
assert_eq!(format!("{:?}", left), format!("{:?}", right))
}
}
mod aot {
use mu::ast::ir::MuName;
use mu::runtime;
use mu::compiler::backend;
use std::path::PathBuf;
use std::process::Command;
use std::process::Output;
const CC : &'static str = "clang";
fn exec (mut cmd: Command) -> Output {
println!("executing: {:?}", cmd);
let output = cmd.output().expect("failed to execute");
println!("---out---");
println!("{}", String::from_utf8_lossy(&output.stdout));
println!("---err---");
println!("{}", String::from_utf8_lossy(&output.stderr));
output
}
fn link_executable_internal (files: Vec<PathBuf>, out: PathBuf) -> PathBuf {
let mut gcc = Command::new(CC);
for file in files {
println!("link with {:?}", file.as_path());
gcc.arg(file.as_path());
}
println!("output as {:?}", out.as_path());
gcc.arg("-o");
gcc.arg(out.as_os_str());
assert!(exec(gcc).status.success());
out
}
fn link_dylib_internal (files: Vec<PathBuf>, out: PathBuf) -> PathBuf {
let mut object_files : Vec<PathBuf> = vec![];
for file in files {
let mut gcc = Command::new(CC);
gcc.arg("-c");
gcc.arg("-fpic");
let mut out = file.clone();
out.set_extension("o");
gcc.arg(file.as_os_str());
gcc.arg("-o");
gcc.arg(out.as_os_str());
object_files.push(out);
exec(gcc);
}
let mut gcc = Command::new(CC);
gcc.arg("-shared");
gcc.arg("-Wl");
gcc.arg("-undefined");
gcc.arg("dynamic_lookup");
for obj in object_files {
gcc.arg(obj.as_os_str());
}
gcc.arg("-o");
gcc.arg(out.as_os_str());
exec(gcc);
out
}
fn get_path_for_mu_func (f: MuName) -> PathBuf {
let mut ret = PathBuf::from(backend::AOT_EMIT_DIR);
ret.push(f);
ret.set_extension("s");
ret
}
fn get_path_for_mu_context () -> PathBuf {
let mut ret = PathBuf::from(backend::AOT_EMIT_DIR);
ret.push(backend::AOT_EMIT_CONTEXT_FILE);
ret
}
pub fn link_primordial (funcs: Vec<MuName>, out: &str) -> PathBuf {
let emit_dir = PathBuf::from(backend::AOT_EMIT_DIR);
let files : Vec<PathBuf> = {
use std::fs;
let mut ret = vec![];
// all interested mu funcs
for func in funcs {
ret.push(get_path_for_mu_func(func));
}
// mu context
ret.push(get_path_for_mu_context());
// copy primoridal entry
let source = PathBuf::from(runtime::PRIMORDIAL_ENTRY);
let mut dest = PathBuf::from(backend::AOT_EMIT_DIR);
dest.push("main.c");
fs::copy(source.as_path(), dest.as_path()).unwrap();
// include the primordial C main
ret.push(dest);
// include mu static lib
let libmu = PathBuf::from("target/debug/libmu.a");
ret.push(libmu);
ret
};
let mut out_path = emit_dir.clone();
out_path.push(out);
link_executable_internal(files, out_path)
}
pub fn execute(executable: PathBuf) {
let run = Command::new(executable.as_os_str());
assert!(exec(run).status.success());
}
pub fn link_dylib (funcs: Vec<MuName>, out: &str) -> PathBuf {
let files = {
let mut ret = vec![];
for func in funcs {
ret.push(get_path_for_mu_func(func));
}
ret.push(get_path_for_mu_context());
ret
};
let mut out_path = PathBuf::from(backend::AOT_EMIT_DIR);
out_path.push(out);
link_dylib_internal(files, out_path)
}
}
mod testutil {
extern crate mu;
extern crate log;
extern crate simple_logger;
extern crate libloading as ll;
use self::mu::compiler::*;
use self::mu::ast::ir::*;
use self::mu::vm::*;
use std::sync::Arc;
use aot;
pub fn compile_fnc<'a>(fnc_name: &'static str, build_fnc: &'a Fn() -> VM) -> ll::Library {
simple_logger::init_with_level(log::LogLevel::Trace).ok();
let vm = Arc::new(build_fnc());
let compiler = Compiler::new(CompilerPolicy::default(), vm.clone());
let func_id = vm.id_of(fnc_name);
{
let funcs = vm.funcs().read().unwrap();
let func = funcs.get(&func_id).unwrap().read().unwrap();
let func_vers = vm.func_vers().read().unwrap();
let mut func_ver = func_vers.get(&func.cur_ver.unwrap()).unwrap().write().unwrap();
compiler.compile(&mut func_ver);
}
backend::emit_context(&vm);
let libname = &format!("lib{}.dylib", fnc_name);
let dylib = aot::link_dylib(vec![Mu(fnc_name)], libname);
ll::Library::new(dylib.as_os_str()).unwrap()
}
}
\ No newline at end of file
......@@ -12,7 +12,7 @@ use self::mu::compiler::*;
use std::sync::Arc;
use std::sync::RwLock;
use std::collections::HashMap;
use aot;
use self::mu::testutil::aot;
#[test]
fn test_instruction_new() {
......
extern crate libloading as ll;
extern crate mu;
use test_ir::test_ir::sum;
use test_ir::test_ir::factorial;
use testutil;
use mu::testutil;
#[test]
fn test_factorial() {
......
......@@ -9,7 +9,7 @@ use self::mu::ast::inst::*;
use self::mu::vm::*;
use self::mu::compiler::*;
use aot;
use self::mu::testutil::aot;
use std::sync::Arc;
use std::sync::RwLock;
......
......@@ -11,7 +11,7 @@ use self::mu::ast::op::*;
use self::mu::vm::*;
use self::mu::compiler::*;
use aot;
use self::mu::testutil::aot;
use std::sync::Arc;
use std::sync::RwLock;
......
......@@ -3,16 +3,16 @@ extern crate libloading as ll;
use test_ir::test_ir::sum;
use test_ir::test_ir::factorial;
use self::mu::ast::ir::*;
use self::mu::ast::op::*;
use self::mu::ast::inst::*;
use self::mu::ast::types::*;
use self::mu::vm::*;
use mu::ast::ir::*;
use mu::ast::op::*;
use mu::ast::inst::*;
use mu::ast::types::*;
use mu::vm::*;
use std::sync::RwLock;
use std::collections::HashMap;
use testutil;
use mu::testutil::compile_fnc;
#[test]
......@@ -54,17 +54,19 @@ fn test_add_8bit_wraparound() {
vm.set_name(blk0.as_entity(), "fnc_v1.blk0".to_string());
// @fnc_v1.blk0.res = ADD <@i8> @0xff_i8 @0x0a_i8
let lc_0xff_i8 = fnc_ver.new_constant(vm.next_id(), c_0xff_i8.clone());
let lc_0x0a_i8 = fnc_ver.new_constant(vm.next_id(), c_0x0a_i8.clone());
let lc_0xff_i8 = fnc_ver.new_constant(c_0xff_i8.clone());
let lc_0x0a_i8 = fnc_ver.new_constant(c_0x0a_i8.clone());
let res = fnc_ver.new_ssa(vm.next_id(), i8.clone());
vm.set_name(res.as_entity(), "fnc_v1.blk0.res".to_string());
let op_add = fnc_ver.new_inst(vm.next_id(), Instruction{
let op_add = fnc_ver.new_inst(Instruction{
hdr: MuEntityHeader::unnamed(vm.next_id()),
value: Some(vec![res.clone_value()]),
ops: RwLock::new(vec![lc_0xff_i8.clone(), lc_0x0a_i8.clone()]),
v: Instruction_::BinOp(BinOp::Add, 0, 1)
});
let op_ret = fnc_ver.new_inst(vm.next_id(), Instruction{
let op_ret = fnc_ver.new_inst(Instruction{
hdr: MuEntityHeader::unnamed(vm.next_id()),
value: None,
ops: RwLock::new(vec![res.clone()]),
v: Instruction_::Return(vec![0])
......@@ -87,7 +89,7 @@ fn test_add_8bit_wraparound() {
vm
}
let lib = testutil::compile_fnc("fnc", &build_fn);
let lib = compile_fnc("fnc", &build_fn);
unsafe {
let fncptr: ll::Symbol<unsafe extern fn () -> u8> = lib.get(b"fnc").unwrap();
assert!(fncptr() == 9);
......@@ -133,17 +135,19 @@ fn test_sub_8bit_wraparound() {
vm.set_name(blk0.as_entity(), "fnc_v1.blk0".to_string());
// @fnc_v1.blk0.res = SUB <@i8> @0x0a_i8 @0xff_i8
let lc_0xff_i8 = fnc_ver.new_constant(vm.next_id(), c_0xff_i8.clone());
let lc_0x0a_i8 = fnc_ver.new_constant(vm.next_id(), c_0x0a_i8.clone());
let lc_0xff_i8 = fnc_ver.new_constant(c_0xff_i8.clone());
let lc_0x0a_i8 = fnc_ver.new_constant(c_0x0a_i8.clone());
let res = fnc_ver.new_ssa(vm.next_id(), i8.clone());
vm.set_name(res.as_entity(), "fnc_v1.blk0.res".to_string());
let op_add = fnc_ver.new_inst(vm.next_id(), Instruction{
let op_add = fnc_ver.new_inst(Instruction{
hdr: MuEntityHeader::unnamed(vm.next_id()),
value: Some(vec![res.clone_value()]),
ops: RwLock::new(vec![lc_0x0a_i8.clone(), lc_0xff_i8.clone()]),
v: Instruction_::BinOp(BinOp::Sub, 0, 1)
});
let op_ret = fnc_ver.new_inst(vm.next_id(), Instruction{
let op_ret = fnc_ver.new_inst(Instruction{
hdr: MuEntityHeader::unnamed(vm.next_id()),
value: None,
ops: RwLock::new(vec![res.clone()]),
v: Instruction_::Return(vec![0])
......@@ -166,7 +170,7 @@ fn test_sub_8bit_wraparound() {
vm
}
let lib = testutil::compile_fnc("fnc", &build_fn);
let lib = compile_fnc("fnc", &build_fn);
unsafe {
let fncptr: ll::Symbol<unsafe extern fn () -> u8> = lib.get(b"fnc").unwrap();
assert!(fncptr() == 0xf5);
......@@ -212,17 +216,19 @@ fn test_mul_8bit_wraparound() {
vm.set_name(blk0.as_entity(), "fnc_v1.blk0".to_string());
// @fnc_v1.blk0.res = MUL <@i8> @0x0a_i8 @0xff_i8
let lc_0xff_i8 = fnc_ver.new_constant(vm.next_id(), c_0xff_i8.clone());
let lc_0x0a_i8 = fnc_ver.new_constant(vm.next_id(), c_0x0a_i8.clone());
let lc_0xff_i8 = fnc_ver.new_constant(c_0xff_i8.clone());
let lc_0x0a_i8 = fnc_ver.new_constant(c_0x0a_i8.clone());
let res = fnc_ver.new_ssa(vm.next_id(), i8.clone());
vm.set_name(res.as_entity(), "fnc_v1.blk0.res".to_string());
let op_add = fnc_ver.new_inst(vm.next_id(), Instruction{
let op_add = fnc_ver.new_inst(Instruction{
hdr: MuEntityHeader::unnamed(vm.next_id()),
value: Some(vec![res.clone_value()]),
ops: RwLock::new(vec![lc_0x0a_i8.clone(), lc_0xff_i8.clone()]),
v: Instruction_::BinOp(BinOp::Mul, 0, 1)
});
let op_ret = fnc_ver.new_inst(vm.next_id(), Instruction{
let op_ret = fnc_ver.new_inst(Instruction{
hdr: MuEntityHeader::unnamed(vm.next_id()),
value: None,
ops: RwLock::new(vec![res.clone()]),
v: Instruction_::Return(vec![0])
......@@ -245,7 +251,7 @@ fn test_mul_8bit_wraparound() {
vm
}
let lib = testutil::compile_fnc("fnc", &build_fn);
let lib = compile_fnc("fnc", &build_fn);
unsafe {
let fncptr: ll::Symbol<unsafe extern fn () -> u8> = lib.get(b"fnc").unwrap();
assert!(fncptr() == 0xf6);
......@@ -291,17 +297,19 @@ fn test_sdiv_i8() {
vm.set_name(blk0.as_entity(), "fnc_v1.blk0".to_string());
// @fnc_v1.blk0.res = SDIV <@i8> @0xff_i8 @0x0a_i8
let lc_0xff_i8 = fnc_ver.new_constant(vm.next_id(), c_0xff_i8.clone());
let lc_0x0a_i8 = fnc_ver.new_constant(vm.next_id(), c_0x0a_i8.clone());
let lc_0xff_i8 = fnc_ver.new_constant(c_0xff_i8.clone());
let lc_0x0a_i8 = fnc_ver.new_constant(c_0x0a_i8.clone());
let res = fnc_ver.new_ssa(vm.next_id(), i8.clone());
vm.set_name(res.as_entity(), "fnc_v1.blk0.res".to_string());
let op_add = fnc_ver.new_inst(vm.next_id(), Instruction{
let op_add = fnc_ver.new_inst(Instruction{
hdr: MuEntityHeader::unnamed(vm.next_id()),
value: Some(vec![res.clone_value()]),
ops: RwLock::new(vec![lc_0xff_i8.clone(), lc_0x0a_i8.clone()]),
v: Instruction_::BinOp(BinOp::Sdiv, 0, 1)
});
let op_ret = fnc_ver.new_inst(vm.next_id(), Instruction{
let op_ret = fnc_ver.new_inst(Instruction{
hdr: MuEntityHeader::unnamed(vm.next_id()),
value: None,
ops: RwLock::new(vec![res.clone()]),
v: Instruction_::Return(vec![0])
......@@ -324,7 +332,7 @@ fn test_sdiv_i8() {
vm
}
let lib = testutil::compile_fnc("fnc", &build_fn);
let lib = compile_fnc("fnc", &build_fn);
unsafe {
let fncptr: ll::Symbol<unsafe extern fn () -> u8> = lib.get(b"fnc").unwrap();
assert!(fncptr() == 0xf4); // -12
......@@ -370,17 +378,19 @@ fn test_urem_i8() {
vm.set_name(blk0.as_entity(), "fnc_v1.blk0".to_string());
// @fnc_v1.blk0.res = UREM <@i8> @0xff_i8 @0x0a_i8
let lc_0xff_i8 = fnc_ver.new_constant(vm.next_id(), c_0xff_i8.clone());
let lc_0x0a_i8 = fnc_ver.new_constant(vm.next_id(), c_0x0a_i8.clone());
let lc_0xff_i8 = fnc_ver.new_constant(c_0xff_i8.clone());
let lc_0x0a_i8 = fnc_ver.new_constant(c_0x0a_i8.clone());
let res = fnc_ver.new_ssa(vm.next_id(), i8.clone());
vm.set_name(res.as_entity(), "fnc_v1.blk0.res".to_string());
let op_add = fnc_ver.new_inst(vm.next_id(), Instruction{
let op_add = fnc_ver.new_inst(Instruction{
hdr: MuEntityHeader::unnamed(vm.next_id()),
value: Some(vec![res.clone_value()]),
ops: RwLock::new(vec![lc_0xff_i8.clone(), lc_0x0a_i8.clone()]),
v: Instruction_::BinOp(BinOp::Urem, 0, 1)
});
let op_ret = fnc_ver.new_inst(vm.next_id(), Instruction{
let op_ret = fnc_ver.new_inst(Instruction{
hdr: MuEntityHeader::unnamed(vm.next_id()),
value: None,
ops: RwLock::new(vec![res.clone()]),
v: Instruction_::Return(vec![0])
......@@ -403,7 +413,7 @@ fn test_urem_i8() {
vm
}
let lib = testutil::compile_fnc("fnc", &build_fn);
let lib = compile_fnc("fnc", &build_fn);
unsafe {
let fncptr: ll::Symbol<unsafe extern fn () -> u8> = lib.get(b"fnc").unwrap();
assert!(fncptr() == 5);
......@@ -450,17 +460,19 @@ fn test_shl() {
vm.set_name(blk0.as_entity(), "fnc_v1.blk0".to_string());
// @fnc_v1.blk0.res = SHL <@i64> @0x6d9f9c1d58324b55 @0x0a_i64
let lc_0x6d9f9c1d58324b55_i64 = fnc_ver.new_constant(vm.next_id(), c_0x6d9f9c1d58324b55_i64.clone());
let lc_0x0a_i64 = fnc_ver.new_constant(vm.next_id(), c_0x0a_i64.clone());
let lc_0x6d9f9c1d58324b55_i64 = fnc_ver.new_constant(c_0x6d9f9c1d58324b55_i64.clone());
let lc_0x0a_i64 = fnc_ver.new_constant(c_0x0a_i64.clone());
let res = fnc_ver.new_ssa(vm.next_id(), i64.clone());
vm.set_name(res.as_entity(), "fnc_v1.blk0.res".to_string());
let op_add = fnc_ver.new_inst(vm.next_id(), Instruction{
let op_add = fnc_ver.new_inst(Instruction{
hdr: MuEntityHeader::unnamed(vm.next_id()),
value: Some(vec![res.clone_value()]),
ops: RwLock::new(vec![lc_0x6d9f9c1d58324b55_i64.clone(), lc_0x0a_i64.clone()]),
v: Instruction_::BinOp(BinOp::Shl, 0, 1)
});
let op_ret = fnc_ver.new_inst(vm.next_id(), Instruction{
let op_ret = fnc_ver.new_inst(Instruction{
hdr: MuEntityHeader::unnamed(vm.next_id()),
value: None,
ops: RwLock::new(vec![res.clone()]),
v: Instruction_::Return(vec![0])
......@@ -483,7 +495,7 @@ fn test_shl() {
vm
}
let lib = testutil::compile_fnc("fnc", &build_fn);
let lib = compile_fnc("fnc", &build_fn);
unsafe {
let fncptr: ll::Symbol<unsafe extern fn () -> u64> = lib.get(b"fnc").unwrap();
assert!(fncptr() == 0x7e707560c92d5400);
......@@ -530,17 +542,19 @@ fn test_lshr() {
vm.set_name(blk0.as_entity(), "fnc_v1.blk0".to_string());
// @fnc_v1.blk0.res = LSHR <@i64> @0x8d9f9c1d58324b55 @0x0a_i64
let lc_0x8d9f9c1d58324b55_i64 = fnc_ver.new_constant(vm.next_id(), c_0x8d9f9c1d58324b55_i64.clone());
let lc_0x0a_i64 = fnc_ver.new_constant(vm.next_id(), c_0x0a_i64.clone());
let lc_0x8d9f9c1d58324b55_i64 = fnc_ver.new_constant(c_0x8d9f9c1d58324b55_i64.clone());
let lc_0x0a_i64 = fnc_ver.new_constant(c_0x0a_i64.clone());
let res = fnc_ver.new_ssa(vm.next_id(), i64.clone());
vm.set_name(res.as_entity(), "fnc_v1.blk0.res".to_string());
let op_add = fnc_ver.new_inst(vm.next_id(), Instruction{
let op_add = fnc_ver.new_inst(Instruction{
hdr: MuEntityHeader::unnamed(vm.next_id()),
value: Some(vec![res.clone_value()]),
ops: RwLock::new(vec![lc_0x8d9f9c1d58324b55_i64.clone(), lc_0x0a_i64.clone()]),
v: Instruction_::BinOp(BinOp::Lshr, 0, 1)
});
let op_ret = fnc_ver.new_inst(vm.next_id(), Instruction{
let op_ret = fnc_ver.new_inst(Instruction{
hdr: MuEntityHeader::unnamed(vm.next_id()),
value: None,
ops: RwLock::new(vec![res.clone()]),
v: Instruction_::Return(vec![0])
......@@ -563,7 +577,7 @@ fn test_lshr() {
vm
}
let lib = testutil::compile_fnc("fnc", &build_fn);
let lib = compile_fnc("fnc", &build_fn);
unsafe {
let fncptr: ll::Symbol<unsafe extern fn () -> u64> = lib.get(b"fnc").unwrap();
assert!(fncptr() == 0x2367E707560C92);
......
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