Invoke panic handler instead of trap for assert_* intrinsics
This commit is contained in:
parent
bcb0862703
commit
c0507a63fb
3 changed files with 75 additions and 44 deletions
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.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");
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue