Refactoring

This commit is contained in:
bjorn3 2018-08-14 18:52:43 +02:00
parent 0978710ffd
commit f67ad9c120
4 changed files with 99 additions and 91 deletions

View file

@ -163,19 +163,6 @@ pub fn get_function_name_and_sig<'a, 'tcx>(
(tcx.symbol_name(inst).as_str().to_string(), sig)
}
impl<'a, 'tcx: 'a> CodegenCx<'a, 'tcx, CurrentBackend> {
pub fn predefine_function(&mut self, inst: Instance<'tcx>) -> (FuncId, Function) {
let (name, sig) = crate::abi::get_function_name_and_sig(self.tcx, inst);
let func_id = self
.module
.declare_function(&name, Linkage::Export, &sig)
.unwrap();
let func =
Function::with_name_signature(ExternalName::user(0, func_id.index() as u32), sig);
(func_id, func)
}
}
impl<'a, 'tcx: 'a> FunctionCx<'a, 'tcx> {
/// Instance must be monomorphized
pub fn get_function_ref(&mut self, inst: Instance<'tcx>) -> FuncRef {
@ -315,6 +302,8 @@ pub fn codegen_fn_prelude<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, start_ebb
}
}).collect::<Vec<(Local, ArgKind, Ty)>>();
fx.bcx.switch_to_block(start_ebb);
match output_pass_mode {
PassMode::NoPass => {
let null = fx.bcx.ins().iconst(types::I64, 0);
@ -418,6 +407,10 @@ pub fn codegen_fn_prelude<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, start_ebb
fx.local_map.insert(local, place);
}
fx.bcx
.ins()
.jump(*fx.ebb_map.get(&START_BLOCK).unwrap(), &[]);
}
pub fn codegen_call<'a, 'tcx: 'a>(

View file

@ -2,7 +2,6 @@ use crate::prelude::*;
pub fn trans_mono_item<'a, 'tcx: 'a>(
cx: &mut CodegenCx<'a, 'tcx, CurrentBackend>,
context: &mut Context,
mono_item: MonoItem<'tcx>,
) {
let tcx = cx.tcx;
@ -21,41 +20,8 @@ pub fn trans_mono_item<'a, 'tcx: 'a>(
String::from_utf8_lossy(&mir.into_inner())
));
let (func_id, mut func) = cx.predefine_function(inst);
let comments = trans_fn(cx, &mut func, inst);
let mut writer = crate::pretty_clif::CommentWriter(comments);
let mut cton = String::new();
::cranelift::codegen::write::decorate_function(&mut writer, &mut cton, &func, None)
.unwrap();
tcx.sess.warn(&cton);
let flags = settings::Flags::new(settings::builder());
match ::cranelift::codegen::verify_function(&func, &flags) {
Ok(_) => {}
Err(err) => {
tcx.sess.err(&format!("{:?}", err));
let pretty_error =
::cranelift::codegen::print_errors::pretty_verifier_error(
&func,
None,
Some(Box::new(writer)),
&err,
);
tcx.sess
.fatal(&format!("cretonne verify error:\n{}", pretty_error));
}
}
context.func = func;
// TODO: cranelift doesn't yet support some of the things needed
if should_codegen(cx.tcx) {
cx.module.define_function(func_id, context).unwrap();
cx.defined_functions.push(func_id);
}
context.clear();
let func_id = trans_fn(cx.tcx, cx.module, &mut cx.constants, &mut cx.context, inst);
cx.defined_functions.push(func_id);
}
Instance {
def: InstanceDef::DropGlue(_, _),
@ -64,7 +30,7 @@ pub fn trans_mono_item<'a, 'tcx: 'a>(
inst => unimpl!("Unimplemented instance {:?}", inst),
},
MonoItem::Static(def_id) => {
crate::constant::codegen_static(cx, def_id);
crate::constant::codegen_static(&mut cx.constants, def_id);
}
MonoItem::GlobalAsm(node_id) => cx
.tcx
@ -73,25 +39,38 @@ pub fn trans_mono_item<'a, 'tcx: 'a>(
}
}
pub fn trans_fn<'a, 'tcx: 'a>(
cx: &mut CodegenCx<'a, 'tcx, CurrentBackend>,
f: &mut Function,
fn trans_fn<'a, 'tcx: 'a>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
module: &mut Module<SimpleJITBackend>,
constants: &mut crate::constant::ConstantCx,
context: &mut Context,
instance: Instance<'tcx>,
) -> HashMap<Inst, String> {
let mir = cx.tcx.optimized_mir(instance.def_id());
let mut func_ctx = FunctionBuilderContext::new();
let mut bcx: FunctionBuilder<Variable> = FunctionBuilder::new(f, &mut func_ctx);
) -> FuncId {
// Step 1. Get mir
let mir = tcx.optimized_mir(instance.def_id());
// Step 2. Declare function
let (name, sig) = get_function_name_and_sig(tcx, instance);
let func_id = module
.declare_function(&name, Linkage::Export, &sig)
.unwrap();
// Step 3. Make FunctionBuilder
let mut func = Function::with_name_signature(ExternalName::user(0, 0), sig);
let mut func_ctx = FunctionBuilderContext::new();
let mut bcx: FunctionBuilder<Variable> = FunctionBuilder::new(&mut func, &mut func_ctx);
// Step 4. Predefine ebb's
let start_ebb = bcx.create_ebb();
bcx.switch_to_block(start_ebb);
let mut ebb_map: HashMap<BasicBlock, Ebb> = HashMap::new();
for (bb, _bb_data) in mir.basic_blocks().iter_enumerated() {
ebb_map.insert(bb, bcx.create_ebb());
}
// Step 5. Make FunctionCx
let mut fx = FunctionCx {
tcx: cx.tcx,
module: &mut cx.module,
tcx,
module,
instance,
mir,
bcx,
@ -102,17 +81,53 @@ pub fn trans_fn<'a, 'tcx: 'a>(
ebb_map,
local_map: HashMap::new(),
comments: HashMap::new(),
constants: &mut cx.constants,
constants,
};
let fx = &mut fx;
crate::abi::codegen_fn_prelude(fx, start_ebb);
// Step 6. Codegen function
crate::abi::codegen_fn_prelude(&mut fx, start_ebb);
codegen_fn_content(&mut fx);
fx.bcx
.ins()
.jump(*fx.ebb_map.get(&START_BLOCK).unwrap(), &[]);
// Step 7. Print function to terminal for debugging
let mut writer = crate::pretty_clif::CommentWriter(fx.comments);
let mut cton = String::new();
::cranelift::codegen::write::decorate_function(&mut writer, &mut cton, &func, None).unwrap();
tcx.sess.warn(&cton);
for (bb, bb_data) in mir.basic_blocks().iter_enumerated() {
// Step 8. Verify function
verify_func(tcx, writer, &func);
// Step 9. Define function
// TODO: cranelift doesn't yet support some of the things needed
if should_codegen(tcx) {
context.func = func;
module.define_function(func_id, context).unwrap();
context.clear();
}
func_id
}
fn verify_func(tcx: TyCtxt, writer: crate::pretty_clif::CommentWriter, func: &Function) {
let flags = settings::Flags::new(settings::builder());
match ::cranelift::codegen::verify_function(&func, &flags) {
Ok(_) => {}
Err(err) => {
tcx.sess.err(&format!("{:?}", err));
let pretty_error = ::cranelift::codegen::print_errors::pretty_verifier_error(
&func,
None,
Some(Box::new(writer)),
&err,
);
tcx.sess
.fatal(&format!("cretonne verify error:\n{}", pretty_error));
}
}
}
fn codegen_fn_content<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>) {
for (bb, bb_data) in fx.mir.basic_blocks().iter_enumerated() {
let ebb = fx.get_ebb(bb);
fx.bcx.switch_to_block(ebb);
@ -208,8 +223,6 @@ pub fn trans_fn<'a, 'tcx: 'a>(
fx.bcx.seal_all_blocks();
fx.bcx.finalize();
fx.comments.clone()
}
fn trans_stmt<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, cur_ebb: Ebb, stmt: &Statement<'tcx>) {

View file

@ -32,8 +32,8 @@ impl ConstantCx {
}
}
pub fn codegen_static<'a, 'tcx: 'a, B: Backend>(cx: &mut CodegenCx<'a, 'tcx, B>, def_id: DefId) {
cx.constants.todo.insert(TodoItem::Static(def_id));
pub fn codegen_static<'a, 'tcx: 'a>(ccx: &mut ConstantCx, def_id: DefId) {
ccx.todo.insert(TodoItem::Static(def_id));
}
pub fn codegen_static_ref<'a, 'tcx: 'a>(

View file

@ -103,6 +103,9 @@ pub struct CodegenCx<'a, 'tcx: 'a, B: Backend + 'a> {
pub module: &'a mut Module<B>,
pub constants: crate::constant::ConstantCx,
pub defined_functions: Vec<FuncId>,
// Cache
pub context: Context,
}
struct CraneliftMetadataLoader;
@ -248,16 +251,25 @@ impl CodegenBackend for CraneliftCodegenBackend {
let isa = cranelift::codegen::isa::lookup(target_lexicon::Triple::host())
.unwrap()
.finish(flags);
let mut module: Module<SimpleJITBackend> = Module::new(SimpleJITBuilder::new());
let mut context = Context::new();
let mut jit_module: Module<SimpleJITBackend> = Module::new(SimpleJITBuilder::new());
let mut faerie_module: Module<FaerieBackend> = Module::new(
FaerieBuilder::new(
isa,
"some_file.o".to_string(),
FaerieTrapCollection::Disabled,
FaerieBuilder::default_libcall_names(),
).unwrap(),
);
let defined_functions = {
use std::io::Write;
let mut cx = CodegenCx {
tcx,
module: &mut module,
module: &mut jit_module,
constants: Default::default(),
defined_functions: Vec::new(),
context: Context::new(),
};
let mut log = ::std::fs::File::create("target/log.txt").unwrap();
@ -273,9 +285,8 @@ impl CodegenBackend for CraneliftCodegenBackend {
for mono_item in mono_items {
let cx = &mut cx;
let context = &mut context;
let res = ::std::panic::catch_unwind(::std::panic::AssertUnwindSafe(move || {
base::trans_mono_item(cx, context, mono_item);
base::trans_mono_item(cx, mono_item);
}));
if let Err(err) = res {
match err.downcast::<NonFatal>() {
@ -304,43 +315,34 @@ impl CodegenBackend for CraneliftCodegenBackend {
let (name, sig) =
crate::abi::get_function_name_and_sig(tcx, Instance::mono(tcx, start_wrapper));
let called_func_id = module
let called_func_id = jit_module
.declare_function(&name, Linkage::Import, &sig)
.unwrap();
for func_id in defined_functions {
if func_id != called_func_id {
module.finalize_function(func_id);
jit_module.finalize_function(func_id);
}
}
tcx.sess.warn("Finalized everything");
let finalized_function: *const u8 = module.finalize_function(called_func_id);
let finalized_function: *const u8 = jit_module.finalize_function(called_func_id);
let f: extern "C" fn(*const u8, isize, *const *const u8) -> isize =
unsafe { ::std::mem::transmute(finalized_function) };
let res = f(0 as *const u8, 0, 0 as *const _);
tcx.sess.warn(&format!("main returned {}", res));
module.finish();
jit_module.finish();
} else if should_codegen(tcx) {
for func_id in defined_functions {
module.finalize_function(func_id);
jit_module.finalize_function(func_id);
}
tcx.sess.warn("Finalized everything");
}
let mut translated_module: Module<FaerieBackend> = Module::new(
FaerieBuilder::new(
isa,
"some_file.o".to_string(),
FaerieTrapCollection::Disabled,
FaerieBuilder::default_libcall_names(),
).unwrap(),
);
Box::new(OngoingCodegen {
product: translated_module.finish(),
product: faerie_module.finish(),
metadata: metadata.raw_data,
crate_name: tcx.crate_name(LOCAL_CRATE),
})