Commit 665eaf74 authored by Eduardo Souza's avatar Eduardo Souza

Added support for GC through MMTk.

parent dd81fdef
...@@ -19,9 +19,12 @@ pub use mu::compiler::*; ...@@ -19,9 +19,12 @@ pub use mu::compiler::*;
use std::collections::HashMap; use std::collections::HashMap;
use mu::ast::ir::*; use mu::ast::ir::*;
use mu::compiler::backend::x86_64::callconv::CallConvResult::STACK;
use mu::utils::*; use mu::utils::*;
use mu::vm::handle::*; use mu::vm::handle::*;
use mu::vm::*; use mu::vm::*;
use std::path::Path;
use ykstackmaps::StackMapParser;
pub fn llvm(wl_fns: Vec<MuID>) -> CompilerPolicy { pub fn llvm(wl_fns: Vec<MuID>) -> CompilerPolicy {
let mut passes: Vec<Box<dyn CompilerPass>> = vec![]; let mut passes: Vec<Box<dyn CompilerPass>> = vec![];
...@@ -281,6 +284,8 @@ pub fn make_boot_image_internal( ...@@ -281,6 +284,8 @@ pub fn make_boot_image_internal(
primordial_threadlocal.map(|x| x.v.as_ref().1) primordial_threadlocal.map(|x| x.v.as_ref().1)
); );
let out_file = output_file.clone();
// link // link
if is_test { if is_test {
link_boot_image_for_testing( link_boot_image_for_testing(
...@@ -297,6 +302,118 @@ pub fn make_boot_image_internal( ...@@ -297,6 +302,118 @@ pub fn make_boot_image_internal(
true true
); );
} }
// parse_stackmap(out_file, vm);
}
}
fn parse_stackmap(path: String, vm: &VM) {
use std::path::PathBuf;
use ykstackmaps::StackMapParser;
let mut file_path = PathBuf::from(&vm.vm_options.flag_aot_emit_dir);
let path = format!("{}", path);
file_path.push(path);
println!("{:?}", file_path);
match StackMapParser::new(&Path::new(&file_path)) {
Err(e) => {
println!("error: {}", e);
unimplemented!();
}
Ok(mut p) => {
p.num_consts();
p.num_funcs();
p.num_stackmaps();
println!(
"num consts: {}, num funcs: {}, num_stackmaps: {}",
p.num_consts(),
p.num_funcs(),
p.num_stackmaps()
);
for stmap_fns in p.iter_functions() {
match stmap_fns {
Ok(stmap) => println!("{:?}", stmap),
Err(e) => {
panic!("error: {}", e);
break; // You must not re-use the iterator upon error.
}
}
}
for stmap_res in p.iter_stackmaps() {
match stmap_res {
Ok(stmap) => {
println!("{:?}", stmap);
match stmap.pos_remainder {
Some(pos) => parse_stackmap_from_pos(
&Path::new(&file_path),
pos
),
None => ()
}
}
Err(e) => {
panic!("error: {}", e);
break; // You must not re-use the iterator upon error.
}
}
}
}
}
unimplemented!();
}
fn parse_stackmap_from_pos(path: &&Path, pos: u64) {
match StackMapParser::new_from_position(path, pos) {
Err(e) => {
println!("error: {}", e);
unimplemented!();
}
Ok(mut p) => {
p.num_consts();
p.num_funcs();
p.num_stackmaps();
println!(
"num consts: {}, num funcs: {}, num_stackmaps: {}",
p.num_consts(),
p.num_funcs(),
p.num_stackmaps()
);
for stmap_fns in p.iter_functions_from_pos(pos) {
match stmap_fns {
Ok(stmap) => println!("{:?}", stmap),
Err(e) => {
panic!("error: {}", e);
break; // You must not re-use the iterator upon error.
}
}
}
for stmap_res in p.iter_stackmaps_from_pos(pos) {
match stmap_res {
Ok(stmap) => {
println!("{:?}", stmap);
match stmap.pos_remainder {
Some(pos) => parse_stackmap_from_pos(path, pos),
None => ()
}
}
Err(e) => {
panic!("error: {}", e);
break; // You must not re-use the iterator upon error.
}
}
}
}
} }
} }
......
...@@ -1194,7 +1194,7 @@ pub unsafe fn gen_instr_exprcall( ...@@ -1194,7 +1194,7 @@ pub unsafe fn gen_instr_exprcall(
(0, Arc::new(String::from("\0"))) (0, Arc::new(String::from("\0")))
} else { } else {
let n = n.get(0).unwrap(); let n = n.get(0).unwrap();
(n.hdr.id(), n.hdr.name()) (n.hdr.id(), Arc::new(format!("{}\0", n.hdr.name())))
} }
} }
None => unimplemented!() None => unimplemented!()
...@@ -1406,7 +1406,8 @@ pub unsafe fn gen_instr_new( ...@@ -1406,7 +1406,8 @@ pub unsafe fn gen_instr_new(
llvm_internal_context: &mut AOTLLVMInternalContext, llvm_internal_context: &mut AOTLLVMInternalContext,
store: &mut HashMap<MuID, LLVMValueRef>, store: &mut HashMap<MuID, LLVMValueRef>,
ins: &Instruction, ins: &Instruction,
llvm_type: LLVMTypeRef llvm_type: LLVMTypeRef,
mu_type: MuID
) { ) {
let ins_value = ins.value.clone().unwrap(); let ins_value = ins.value.clone().unwrap();
if ins_value.len() > 1 { if ins_value.len() > 1 {
...@@ -1417,22 +1418,30 @@ pub unsafe fn gen_instr_new( ...@@ -1417,22 +1418,30 @@ pub unsafe fn gen_instr_new(
format!("{}_ptr\0", ins_value.get(0).unwrap().hdr.name().clone()); format!("{}_ptr\0", ins_value.get(0).unwrap().hdr.name().clone());
let name = format!("{}\0", ins_value.get(0).unwrap().hdr.name().clone()); let name = format!("{}\0", ins_value.get(0).unwrap().hdr.name().clone());
let calloc_fn = LLVMGetNamedFunction( let muentry_alloc_mmtk_fn = LLVMGetNamedFunction(
llvm_internal_context.module, llvm_internal_context.module,
"calloc\0".as_ptr() as *const c_char "muentry_alloc_mmtk\0".as_ptr() as *const c_char
); );
if calloc_fn.is_null() { if muentry_alloc_mmtk_fn.is_null() {
panic!("Function has not been defined."); panic!("Function has not been defined.");
} }
let data_layout = LLVMGetModuleDataLayout(llvm_internal_context.module); let data_layout = LLVMGetModuleDataLayout(llvm_internal_context.module);
let size = LLVMABISizeOfType(data_layout, llvm_type); let size = LLVMABISizeOfType(data_layout, llvm_type);
let size = LLVMConstInt(LLVMInt64Type(), size, false as i32); let size = LLVMConstInt(LLVMInt64Type(), size, false as i32);
let alignment = LLVMABIAlignmentOfType(data_layout, llvm_type);
let alignment =
LLVMConstInt(LLVMInt64Type(), alignment as u64, false as i32);
let mut args = vec![LLVMConstInt(LLVMInt64Type(), 1, false as i32), size]; let mut args = vec![
size,
alignment,
LLVMConstInt(LLVMInt64Type(), 0, false as i32),
// LLVMConstInt(LLVMInt32Type(), mu_type as u64, 0),
];
let ptr = LLVMBuildCall( let ptr = LLVMBuildCall(
llvm_internal_context.builder, llvm_internal_context.builder,
calloc_fn, muentry_alloc_mmtk_fn,
args.as_mut_ptr(), args.as_mut_ptr(),
args.len() as u32, args.len() as u32,
name_ptr.as_str().as_ptr() as *const c_char name_ptr.as_str().as_ptr() as *const c_char
......
...@@ -33,9 +33,7 @@ use crate::instr::*; ...@@ -33,9 +33,7 @@ use crate::instr::*;
use llvm_sys::initialization::{ use llvm_sys::initialization::{
LLVMInitializeCodeGen, LLVMInitializeCore, LLVMInitializeScalarOpts LLVMInitializeCodeGen, LLVMInitializeCore, LLVMInitializeScalarOpts
}; };
use llvm_sys::transforms::scalar::{ use llvm_sys::transforms::scalar::{LLVMAddCFGSimplificationPass, LLVMAddGVNPass, LLVMAddReassociatePass};
LLVMAddCFGSimplificationPass, LLVMAddGVNPass
};
use std::any::Any; use std::any::Any;
use std::borrow::Borrow; use std::borrow::Borrow;
use std::collections::HashMap; use std::collections::HashMap;
...@@ -257,8 +255,62 @@ fn visit_inst_custom( ...@@ -257,8 +255,62 @@ fn visit_inst_custom(
); );
}, },
// visited to declare function calloc // visited to declare function calloc
mu::ast::inst::Instruction_::New(_) mu::ast::inst::Instruction_::New(_) => unsafe {
| mu::ast::inst::Instruction_::NewHybrid(_, _) => unsafe { let function_name =
MuName::new(String::from("muentry_alloc_mmtk"));
let i8_type = Arc::new(MuType::new(0, MuType_::Int(8)));
let refi8_type =
Arc::new(MuType::new(0, MuType_::Ref(i8_type)));
let llvm_refi8_type =
gen_llvm_type(llvm_internal_context, &refi8_type);
let return_type = llvm_refi8_type.clone();
let arg_type = Arc::new(MuType::new(0, MuType_::Int(64)));
let llvm_arg_type =
gen_llvm_type(llvm_internal_context, &arg_type);
let llvm_arg_types = vec![
llvm_arg_type.clone(),
llvm_arg_type.clone(),
llvm_arg_type.clone(),
];
add_function_to_module(
llvm_internal_context,
function_name,
llvm_arg_types,
return_type,
false
);
let function_name =
MuName::new(String::from("llvm.experimental.stackmap"));
let i8_type = Arc::new(MuType::new(0, MuType_::Int(8)));
let refi8_type =
Arc::new(MuType::new(0, MuType_::Ref(i8_type)));
let llvm_refi8_type =
gen_llvm_type(llvm_internal_context, &refi8_type);
let i32_type = Arc::new(MuType::new(0, MuType_::Int(32)));
let llvm_i32_type =
gen_llvm_type(llvm_internal_context, &i32_type);
let i64_type = Arc::new(MuType::new(0, MuType_::Int(64)));
let llvm_i64_type =
gen_llvm_type(llvm_internal_context, &i64_type);
let return_type = LLVMVoidType();
let llvm_arg_types =
vec![llvm_i64_type.clone(), llvm_i32_type.clone()];
add_function_to_module(
llvm_internal_context,
function_name,
llvm_arg_types,
return_type,
true
);
},
mu::ast::inst::Instruction_::NewHybrid(_, _) => unsafe {
let function_name = MuName::new(String::from("calloc")); let function_name = MuName::new(String::from("calloc"));
let i8_type = Arc::new(MuType::new(0, MuType_::Int(8))); let i8_type = Arc::new(MuType::new(0, MuType_::Int(8)));
let refi8_type = let refi8_type =
...@@ -707,6 +759,9 @@ unsafe fn emit_llvm_asm_code( ...@@ -707,6 +759,9 @@ unsafe fn emit_llvm_asm_code(
function_type function_type
); );
// set function as GC-able
LLVMSetGC(function, "statepoint-example\0".as_ptr() as *const c_char);
llvm_internal_context.curr_fn = Some(function); llvm_internal_context.curr_fn = Some(function);
// functions can be called by their unmangled name // functions can be called by their unmangled name
...@@ -786,7 +841,7 @@ unsafe fn emit_llvm_asm_code( ...@@ -786,7 +841,7 @@ unsafe fn emit_llvm_asm_code(
} }
generate_llvm_ir(&llvm_internal_context, func, vm); generate_llvm_ir(&llvm_internal_context, func, vm);
generate_llvm_asm(&llvm_internal_context, func, vm); // generate_llvm_asm(&llvm_internal_context, func, vm);
llvm_internal_context.curr_fn = None; llvm_internal_context.curr_fn = None;
} }
...@@ -1107,11 +1162,11 @@ pub unsafe fn gen_llvm_type( ...@@ -1107,11 +1162,11 @@ pub unsafe fn gen_llvm_type(
} }
MuType_::UPtr(mu_type) => { MuType_::UPtr(mu_type) => {
if mu_type.is_void() { if mu_type.is_void() {
LLVMPointerType(LLVMInt8Type(), 1) LLVMPointerType(LLVMInt8Type(), 0)
} else { } else {
let internal_type = let internal_type =
gen_llvm_type(llvm_internal_context, mu_type); gen_llvm_type(llvm_internal_context, mu_type);
LLVMPointerType(internal_type, 1) LLVMPointerType(internal_type, 0)
} }
} }
MuType_::FuncRef(sig) => LLVMPointerType( MuType_::FuncRef(sig) => LLVMPointerType(
...@@ -1383,7 +1438,7 @@ unsafe fn gen_llvm_instruction( ...@@ -1383,7 +1438,7 @@ unsafe fn gen_llvm_instruction(
} }
mu::ast::inst::Instruction_::New(mu_type) => { mu::ast::inst::Instruction_::New(mu_type) => {
let llvm_type = gen_llvm_type(llvm_internal_context, mu_type); let llvm_type = gen_llvm_type(llvm_internal_context, mu_type);
gen_instr_new(llvm_internal_context, store, ins, llvm_type); gen_instr_new(llvm_internal_context, store, ins, llvm_type, mu_type.hdr.id());
LLVMSetGC( LLVMSetGC(
llvm_internal_context.curr_fn.unwrap(), llvm_internal_context.curr_fn.unwrap(),
"statepoint-example\0".as_ptr() as *const c_char "statepoint-example\0".as_ptr() as *const c_char
...@@ -1746,13 +1801,15 @@ unsafe fn generate_llvm_ir( ...@@ -1746,13 +1801,15 @@ unsafe fn generate_llvm_ir(
let name = CString::new(path).unwrap(); let name = CString::new(path).unwrap();
let function_pass_manager = LLVMCreateFunctionPassManagerForModule(llvm_internal_context.module);
llvm_sys::core::LLVMPrintModuleToFile( llvm_sys::core::LLVMPrintModuleToFile(
llvm_internal_context.module, llvm_internal_context.module,
name.as_ptr(), name.as_ptr(),
ptr::null_mut() ptr::null_mut()
); );
optimize_ir(llvm_internal_context, func, vm); // optimize_ir(llvm_internal_context, func, vm);
} }
unsafe fn optimize_ir( unsafe fn optimize_ir(
...@@ -1788,6 +1845,7 @@ unsafe fn optimize_ir( ...@@ -1788,6 +1845,7 @@ unsafe fn optimize_ir(
let mut llc = Command::new(get_llvm_optimizer()); let mut llc = Command::new(get_llvm_optimizer());
// rewrite statepoints for GC // rewrite statepoints for GC
llc.arg("-place-safepoints");
llc.arg("-rewrite-statepoints-for-gc"); llc.arg("-rewrite-statepoints-for-gc");
// print as IR // print as IR
...@@ -1818,7 +1876,7 @@ unsafe fn generate_llvm_asm( ...@@ -1818,7 +1876,7 @@ unsafe fn generate_llvm_asm(
// create 'emit' directory // create 'emit' directory
mu::vm::uir_output::create_emit_directory(vm); mu::vm::uir_output::create_emit_directory(vm);
let input = format!("{}-opt.ll", function_name); let input = format!("{}.ll", function_name);
let mut input_path = path::PathBuf::new(); let mut input_path = path::PathBuf::new();
input_path.push(&vm.vm_options.flag_aot_emit_dir); input_path.push(&vm.vm_options.flag_aot_emit_dir);
input_path.push(&input); input_path.push(&input);
...@@ -1841,6 +1899,17 @@ unsafe fn generate_llvm_asm( ...@@ -1841,6 +1899,17 @@ unsafe fn generate_llvm_asm(
// position independent code // position independent code
llc.arg("-relocation-model=pic"); llc.arg("-relocation-model=pic");
// disable frame pointer elimination
llc.arg("-disable-fp-elim");
// emit functions into separate sections
llc.arg("-function-sections");
// emit data into separate sections
llc.arg("-data-sections");
// llc.arg("-frame-pointer=all");
llc.arg("-filetype=asm"); llc.arg("-filetype=asm");
llc.arg(output_command); llc.arg(output_command);
......
...@@ -4026,7 +4026,7 @@ macro_rules! build_and_run_llvm_test { ...@@ -4026,7 +4026,7 @@ macro_rules! build_and_run_llvm_test {
whitelist.push(func_id); whitelist.push(func_id);
vm.set_primordial_thread(func_id, true, vec![]); vm.set_primordial_thread(func_id, true, vec![]);
let image_name = format!("{}_{}", stringify!($test_name), stringify!($tester_name)) ; let image_name = format!("{}", stringify!($tester_name)) ;
let primordial_func = vm.handle_from_func(func_id); let primordial_func = vm.handle_from_func(func_id);
vm.set_primordial_thread(func_id, true, vec![]); vm.set_primordial_thread(func_id, true, vec![]);
......
...@@ -96,6 +96,9 @@ pub mod test_exception; ...@@ -96,6 +96,9 @@ pub mod test_exception;
#[cfg(test)] #[cfg(test)]
pub mod test_floatingpoint; pub mod test_floatingpoint;
#[cfg(test)]
pub mod test_gc;
#[cfg(test)] #[cfg(test)]
pub mod test_global; pub mod test_global;
......
This diff is collapsed.
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