1
Fork 0

Invoke panic handler instead of trap for assert_* intrinsics

This commit is contained in:
bjorn3 2020-09-29 13:22:01 +02:00
parent bcb0862703
commit c0507a63fb
3 changed files with 75 additions and 44 deletions

View file

@ -274,47 +274,26 @@ fn codegen_fn_content(fx: &mut FunctionCx<'_, '_, impl Backend>) {
fx.bcx.switch_to_block(failure); fx.bcx.switch_to_block(failure);
fx.bcx.ins().nop(); fx.bcx.ins().nop();
let location = fx match msg {
.get_caller_location(bb_data.terminator().source_info.span)
.load_scalar(fx);
let args;
let lang_item = match msg {
AssertKind::BoundsCheck { ref len, ref index } => { AssertKind::BoundsCheck { ref len, ref index } => {
let len = trans_operand(fx, len).load_scalar(fx); let len = trans_operand(fx, len).load_scalar(fx);
let index = trans_operand(fx, index).load_scalar(fx); let index = trans_operand(fx, index).load_scalar(fx);
args = [index, len, location]; let location = fx
rustc_hir::LangItem::PanicBoundsCheck .get_caller_location(bb_data.terminator().source_info.span)
.load_scalar(fx);
codegen_panic_inner(
fx,
rustc_hir::LangItem::PanicBoundsCheck,
&[index, len, location],
bb_data.terminator().source_info.span,
);
} }
_ => { _ => {
let msg_str = msg.description(); let msg_str = msg.description();
let msg_ptr = fx.anonymous_str("assert", msg_str); codegen_panic(fx, msg_str, bb_data.terminator().source_info.span);
let msg_len = fx
.bcx
.ins()
.iconst(fx.pointer_type, i64::try_from(msg_str.len()).unwrap());
args = [msg_ptr, msg_len, location];
rustc_hir::LangItem::Panic
} }
}; }
let def_id = fx.tcx.lang_items().require(lang_item).unwrap_or_else(|s| {
fx.tcx
.sess
.span_fatal(bb_data.terminator().source_info.span, &s)
});
let instance = Instance::mono(fx.tcx, def_id).polymorphize(fx.tcx);
let symbol_name = fx.tcx.symbol_name(instance).name;
fx.lib_call(
&*symbol_name,
vec![fx.pointer_type, fx.pointer_type, fx.pointer_type],
vec![],
&args,
);
crate::trap::trap_unreachable(fx, "panic lang item returned");
} }
TerminatorKind::SwitchInt { TerminatorKind::SwitchInt {
@ -997,3 +976,45 @@ pub(crate) fn trans_operand<'tcx>(
Operand::Constant(const_) => crate::constant::trans_constant(fx, const_), Operand::Constant(const_) => crate::constant::trans_constant(fx, const_),
} }
} }
pub(crate) fn codegen_panic<'tcx>(
fx: &mut FunctionCx<'_, 'tcx, impl Backend>,
msg_str: &str,
span: Span,
) {
let location = fx.get_caller_location(span).load_scalar(fx);
let msg_ptr = fx.anonymous_str("assert", msg_str);
let msg_len = fx
.bcx
.ins()
.iconst(fx.pointer_type, i64::try_from(msg_str.len()).unwrap());
let args = [msg_ptr, msg_len, location];
codegen_panic_inner(fx, rustc_hir::LangItem::Panic, &args, span);
}
pub(crate) fn codegen_panic_inner<'tcx>(
fx: &mut FunctionCx<'_, 'tcx, impl Backend>,
lang_item: rustc_hir::LangItem,
args: &[Value],
span: Span,
) {
let def_id = fx
.tcx
.lang_items()
.require(lang_item)
.unwrap_or_else(|s| fx.tcx.sess.span_fatal(span, &s));
let instance = Instance::mono(fx.tcx, def_id).polymorphize(fx.tcx);
let symbol_name = fx.tcx.symbol_name(instance).name;
fx.lib_call(
&*symbol_name,
vec![fx.pointer_type, fx.pointer_type, fx.pointer_type],
vec![],
args,
);
crate::trap::trap_unreachable(fx, "panic lang item returned");
}

View file

@ -413,13 +413,13 @@ pub(crate) fn codegen_intrinsic_call<'tcx>(
// Insert non returning intrinsics here // Insert non returning intrinsics here
match intrinsic { match intrinsic {
"abort" => { "abort" => {
trap_panic(fx, "Called intrinsic::abort."); trap_abort(fx, "Called intrinsic::abort.");
} }
"unreachable" => { "unreachable" => {
trap_unreachable(fx, "[corruption] Called intrinsic::unreachable."); trap_unreachable(fx, "[corruption] Called intrinsic::unreachable.");
} }
"transmute" => { "transmute" => {
trap_unreachable(fx, "[corruption] Transmuting to uninhabited type."); crate::base::codegen_panic(fx, "Transmuting to uninhabited type.", span);
} }
_ => unimplemented!("unsupported instrinsic {}", intrinsic), _ => unimplemented!("unsupported instrinsic {}", intrinsic),
} }
@ -819,17 +819,29 @@ pub(crate) fn codegen_intrinsic_call<'tcx>(
assert_inhabited | assert_zero_valid | assert_uninit_valid, <T> () { assert_inhabited | assert_zero_valid | assert_uninit_valid, <T> () {
let layout = fx.layout_of(T); let layout = fx.layout_of(T);
if layout.abi.is_uninhabited() { if layout.abi.is_uninhabited() {
crate::trap::trap_panic(fx, &format!("attempted to instantiate uninhabited type `{}`", T)); crate::base::codegen_panic(
fx,
&format!("attempted to instantiate uninhabited type `{}`", T),
span,
);
return; return;
} }
if intrinsic == "assert_zero_valid" && !layout.might_permit_raw_init(fx, /*zero:*/ true).unwrap() { if intrinsic == "assert_zero_valid" && !layout.might_permit_raw_init(fx, /*zero:*/ true).unwrap() {
crate::trap::trap_panic(fx, &format!("attempted to zero-initialize type `{}`, which is invalid", T)); crate::base::codegen_panic(
fx,
&format!("attempted to zero-initialize type `{}`, which is invalid", T),
span,
);
return; return;
} }
if intrinsic == "assert_uninit_valid" && !layout.might_permit_raw_init(fx, /*zero:*/ false).unwrap() { if intrinsic == "assert_uninit_valid" && !layout.might_permit_raw_init(fx, /*zero:*/ false).unwrap() {
crate::trap::trap_panic(fx, &format!("attempted to leave type `{}` uninitialized, which is invalid", T)); crate::base::codegen_panic(
fx,
&format!("attempted to leave type `{}` uninitialized, which is invalid", T),
span,
);
return; return;
} }
}; };

View file

@ -28,15 +28,13 @@ fn codegen_print(fx: &mut FunctionCx<'_, '_, impl cranelift_module::Backend>, ms
fx.bcx.ins().call(puts, &[msg_ptr]); fx.bcx.ins().call(puts, &[msg_ptr]);
} }
/// Use this when `rustc_codegen_llvm` would insert a call to the panic handler. /// Trap code: user1
/// pub(crate) fn trap_abort(
/// Trap code: user0
pub(crate) fn trap_panic(
fx: &mut FunctionCx<'_, '_, impl cranelift_module::Backend>, fx: &mut FunctionCx<'_, '_, impl cranelift_module::Backend>,
msg: impl AsRef<str>, msg: impl AsRef<str>,
) { ) {
codegen_print(fx, msg.as_ref()); codegen_print(fx, msg.as_ref());
fx.bcx.ins().trap(TrapCode::User(0)); fx.bcx.ins().trap(TrapCode::User(1));
} }
/// Use this for example when a function call should never return. This will fill the current block, /// Use this for example when a function call should never return. This will fill the current block,