diff --git a/src/abi.rs b/src/abi.rs index da28dc04c4b..036ea80d7ee 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -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::>(); + 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>( diff --git a/src/base.rs b/src/base.rs index 40c858508d3..1c14c94065c 100644 --- a/src/base.rs +++ b/src/base.rs @@ -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, + constants: &mut crate::constant::ConstantCx, + context: &mut Context, instance: Instance<'tcx>, -) -> HashMap { - let mir = cx.tcx.optimized_mir(instance.def_id()); - let mut func_ctx = FunctionBuilderContext::new(); - let mut bcx: FunctionBuilder = 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 = 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 = 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>) { diff --git a/src/constant.rs b/src/constant.rs index 594cafc44fb..868bf2a8181 100644 --- a/src/constant.rs +++ b/src/constant.rs @@ -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>( diff --git a/src/lib.rs b/src/lib.rs index b89586c9415..9e6e9acf4c0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -103,6 +103,9 @@ pub struct CodegenCx<'a, 'tcx: 'a, B: Backend + 'a> { pub module: &'a mut Module, pub constants: crate::constant::ConstantCx, pub defined_functions: Vec, + + // 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 = Module::new(SimpleJITBuilder::new()); - let mut context = Context::new(); + let mut jit_module: Module = Module::new(SimpleJITBuilder::new()); + let mut faerie_module: Module = 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::() { @@ -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 = 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), })