Invoke panic handler instead of trap for assert_* intrinsics
This commit is contained in:
parent
bcb0862703
commit
c0507a63fb
89
src/base.rs
89
src/base.rs
@ -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");
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user