diff --git a/src/abi.rs b/src/abi.rs index 1e1549469e1..531e4f063af 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -590,7 +590,7 @@ pub fn codegen_terminator_call<'a, 'tcx: 'a>( let ret_ebb = fx.get_ebb(dest); fx.bcx.ins().jump(ret_ebb, &[]); } else { - trap_unreachable(&mut fx.bcx); + trap_unreachable(fx, "[corruption] Diverging function returned"); } } diff --git a/src/base.rs b/src/base.rs index 312e8a85d79..3f9fef329c3 100644 --- a/src/base.rs +++ b/src/base.rs @@ -108,9 +108,28 @@ fn trans_fn<'a, 'clif, 'tcx: 'a, B: Backend + 'static>( let start_ebb = bcx.create_ebb(); bcx.append_ebb_params_for_function_params(start_ebb); bcx.switch_to_block(start_ebb); - crate::trap::trap_unreachable(&mut bcx); - bcx.seal_all_blocks(); - bcx.finalize(); + + let mut fx = FunctionCx { + tcx, + module: cx.module, + pointer_type: pointer_ty(tcx), + + instance, + mir, + + bcx, + ebb_map: HashMap::new(), + local_map: HashMap::new(), + + clif_comments: crate::pretty_clif::CommentWriter::new(tcx, instance), + constants: &mut cx.ccx, + caches: &mut cx.caches, + source_info_set: indexmap::IndexSet::new(), + }; + + crate::trap::trap_unreachable(&mut fx, "[unimplemented] Called function with u128 or i128 as argument."); + fx.bcx.seal_all_blocks(); + fx.bcx.finalize(); // Step 2b3. Define function cx.caches.context.func = func; @@ -254,7 +273,7 @@ fn codegen_fn_content<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx, impl Backend>) TerminatorKind::Assert { cond, expected, - msg: _, + msg, target, cleanup: _, } => { @@ -267,7 +286,7 @@ fn codegen_fn_content<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx, impl Backend>) } else { fx.bcx.ins().brz(cond, target, &[]); }; - trap_panic(&mut fx.bcx); + trap_panic(fx, format!("[panic] Assert {:?} failed.", msg)); } TerminatorKind::SwitchInt { @@ -294,8 +313,11 @@ fn codegen_fn_content<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx, impl Backend>) } => { crate::abi::codegen_terminator_call(fx, func, args, destination); } - TerminatorKind::Resume | TerminatorKind::Abort | TerminatorKind::Unreachable => { - trap_unreachable(&mut fx.bcx); + TerminatorKind::Resume | TerminatorKind::Abort => { + trap_unreachable(fx, "[corruption] Unwinding bb reached."); + } + TerminatorKind::Unreachable => { + trap_unreachable(fx, "[corruption] Hit unreachable code."); } TerminatorKind::Yield { .. } | TerminatorKind::FalseEdges { .. } @@ -742,7 +764,7 @@ pub fn trans_get_discriminant<'a, 'tcx: 'a>( let layout = place.layout(); if layout.abi == layout::Abi::Uninhabited { - return trap_unreachable_ret_value(fx, dest_layout); + return trap_unreachable_ret_value(fx, dest_layout, "[panic] Tried to get discriminant for uninhabited type."); } let (discr_scalar, discr_kind) = match &layout.variants { diff --git a/src/constant.rs b/src/constant.rs index 03ab11d9e59..738349275b8 100644 --- a/src/constant.rs +++ b/src/constant.rs @@ -69,7 +69,13 @@ pub fn trans_promoted<'a, 'tcx: 'a>( debug_assert_eq!(cplace.layout(), fx.layout_of(dest_ty)); cplace } - Err(_) => crate::trap::trap_unreachable_ret_place(fx, fx.layout_of(dest_ty)), + Err(_) => { + crate::trap::trap_unreachable_ret_place( + fx, + fx.layout_of(dest_ty), + "[panic] Tried to get value of promoted value with errored during const eval.", + ) + } } } diff --git a/src/intrinsics.rs b/src/intrinsics.rs index 34b58c5b407..22a527f0ab3 100644 --- a/src/intrinsics.rs +++ b/src/intrinsics.rs @@ -103,10 +103,10 @@ pub fn codegen_intrinsic_call<'a, 'tcx: 'a>( // Insert non returning intrinsics here match intrinsic { "abort" => { - trap_panic(&mut fx.bcx); + trap_panic(fx, "Called intrinisc::abort."); } "unreachable" => { - trap_unreachable(&mut fx.bcx); + trap_unreachable(fx, "[corruption] Called intrinsic::unreachable."); } _ => unimplemented!("unsupported instrinsic {}", intrinsic), } @@ -339,7 +339,7 @@ pub fn codegen_intrinsic_call<'a, 'tcx: 'a>( }; init, () { if ret.layout().abi == Abi::Uninhabited { - crate::trap::trap_panic(&mut fx.bcx); + crate::trap::trap_panic(fx, "[panic] Called intrinsic::init for uninhabited type."); return; } @@ -377,7 +377,7 @@ pub fn codegen_intrinsic_call<'a, 'tcx: 'a>( }; uninit, () { if ret.layout().abi == Abi::Uninhabited { - crate::trap::trap_panic(&mut fx.bcx); + crate::trap::trap_panic(fx, "[panic] Called intrinsic::uninit for uninhabited type."); return; } @@ -412,7 +412,7 @@ pub fn codegen_intrinsic_call<'a, 'tcx: 'a>( }; panic_if_uninhabited, () { if fx.layout_of(T).abi.is_uninhabited() { - crate::trap::trap_panic(&mut fx.bcx); + crate::trap::trap_panic(fx, "[panic] Called intrinsic::panic_if_uninhabited for uninhabited type."); return; } }; @@ -492,6 +492,6 @@ pub fn codegen_intrinsic_call<'a, 'tcx: 'a>( let ret_ebb = fx.get_ebb(dest); fx.bcx.ins().jump(ret_ebb, &[]); } else { - trap_unreachable(&mut fx.bcx); + trap_unreachable(fx, "[corruption] Diverging intrinsic returned."); } } diff --git a/src/trap.rs b/src/trap.rs index 9a517ae7749..f492bcf4b1e 100644 --- a/src/trap.rs +++ b/src/trap.rs @@ -1,23 +1,51 @@ use crate::prelude::*; +fn codegen_print(fx: &mut FunctionCx<'_, '_, impl cranelift_module::Backend>, msg: &str) { + let puts = fx.module.declare_function("puts", Linkage::Import, &Signature { + call_conv: CallConv::SystemV, + params: vec![AbiParam::new(pointer_ty(fx.tcx))], + returns: vec![], + }).unwrap(); + let puts = fx.module.declare_func_in_func(puts, &mut fx.bcx.func); + + let symbol_name = fx.tcx.symbol_name(fx.instance); + let msg_bytes = format!("trap at {:?} ({}): {}\0", fx.instance, symbol_name, msg).into_bytes().into_boxed_slice(); + let mut data_ctx = DataContext::new(); + data_ctx.define(msg_bytes); + let msg_id = fx.module.declare_data(&(symbol_name.as_str().to_string() + msg), Linkage::Local, false).unwrap(); + + // Ignore DuplicateDefinition error, as the data will be the same + let _ = fx.module.define_data(msg_id, &data_ctx); + + let local_msg_id = fx.module.declare_data_in_func(msg_id, fx.bcx.func); + let msg_ptr = fx.bcx.ins().global_value(pointer_ty(fx.tcx), local_msg_id); + fx.bcx.ins().call(puts, &[msg_ptr]); +} + /// Trap code: user0 -pub fn trap_panic(bcx: &mut FunctionBuilder) { - bcx.ins().trap(TrapCode::User(0)); +pub fn trap_panic(fx: &mut FunctionCx<'_, '_, impl cranelift_module::Backend>, msg: impl AsRef) { + codegen_print(fx, msg.as_ref()); + fx.bcx.ins().trap(TrapCode::User(0)); } /// Trap code: user65535 -pub fn trap_unreachable(bcx: &mut FunctionBuilder) { - bcx.ins().trap(TrapCode::User(!0)); +pub fn trap_unreachable(fx: &mut FunctionCx<'_, '_, impl cranelift_module::Backend>, msg: impl AsRef) { + codegen_print(fx, msg.as_ref()); + fx.bcx.ins().trap(TrapCode::User(!0)); } -pub fn trap_unreachable_ret_value<'tcx>(fx: &mut FunctionCx<'_, 'tcx, impl cranelift_module::Backend>, dest_layout: TyLayout<'tcx>) -> CValue<'tcx> { +/// Trap code: user65535 +pub fn trap_unreachable_ret_value<'tcx>(fx: &mut FunctionCx<'_, 'tcx, impl cranelift_module::Backend>, dest_layout: TyLayout<'tcx>, msg: impl AsRef) -> CValue<'tcx> { + codegen_print(fx, msg.as_ref()); let true_ = fx.bcx.ins().iconst(types::I32, 1); fx.bcx.ins().trapnz(true_, TrapCode::User(!0)); let zero = fx.bcx.ins().iconst(fx.pointer_type, 0); CValue::ByRef(zero, dest_layout) } -pub fn trap_unreachable_ret_place<'tcx>(fx: &mut FunctionCx<'_, 'tcx, impl cranelift_module::Backend>, dest_layout: TyLayout<'tcx>) -> CPlace<'tcx> { +/// Trap code: user65535 +pub fn trap_unreachable_ret_place<'tcx>(fx: &mut FunctionCx<'_, 'tcx, impl cranelift_module::Backend>, dest_layout: TyLayout<'tcx>, msg: impl AsRef) -> CPlace<'tcx> { + codegen_print(fx, msg.as_ref()); let true_ = fx.bcx.ins().iconst(types::I32, 1); fx.bcx.ins().trapnz(true_, TrapCode::User(!0)); let zero = fx.bcx.ins().iconst(fx.pointer_type, 0);