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.ins().nop();
let location = fx
.get_caller_location(bb_data.terminator().source_info.span)
.load_scalar(fx);
let args;
let lang_item = match msg {
match msg {
AssertKind::BoundsCheck { ref len, ref index } => {
let len = trans_operand(fx, len).load_scalar(fx);
let index = trans_operand(fx, index).load_scalar(fx);
args = [index, len, location];
rustc_hir::LangItem::PanicBoundsCheck
let location = fx
.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_ptr = fx.anonymous_str("assert", msg_str);
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
codegen_panic(fx, msg_str, bb_data.terminator().source_info.span);
}
};
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 {
@ -997,3 +976,45 @@ pub(crate) fn trans_operand<'tcx>(
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
match intrinsic {
"abort" => {
trap_panic(fx, "Called intrinsic::abort.");
trap_abort(fx, "Called intrinsic::abort.");
}
"unreachable" => {
trap_unreachable(fx, "[corruption] Called intrinsic::unreachable.");
}
"transmute" => {
trap_unreachable(fx, "[corruption] Transmuting to uninhabited type.");
crate::base::codegen_panic(fx, "Transmuting to uninhabited type.", span);
}
_ => unimplemented!("unsupported instrinsic {}", intrinsic),
}
@ -819,17 +819,29 @@ pub(crate) fn codegen_intrinsic_call<'tcx>(
assert_inhabited | assert_zero_valid | assert_uninit_valid, <T> () {
let layout = fx.layout_of(T);
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;
}
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;
}
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;
}
};

View File

@ -28,15 +28,13 @@ fn codegen_print(fx: &mut FunctionCx<'_, '_, impl cranelift_module::Backend>, ms
fx.bcx.ins().call(puts, &[msg_ptr]);
}
/// Use this when `rustc_codegen_llvm` would insert a call to the panic handler.
///
/// Trap code: user0
pub(crate) fn trap_panic(
/// Trap code: user1
pub(crate) fn trap_abort(
fx: &mut FunctionCx<'_, '_, impl cranelift_module::Backend>,
msg: impl AsRef<str>,
) {
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,