Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 37 additions & 7 deletions compiler/rustc_codegen_cranelift/example/mini_core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -493,18 +493,48 @@ macro_rules! panic_const {
}

panic_const! {
panic_const_add_overflow = "attempt to add with overflow",
panic_const_sub_overflow = "attempt to subtract with overflow",
panic_const_mul_overflow = "attempt to multiply with overflow",
panic_const_div_overflow = "attempt to divide with overflow",
panic_const_rem_overflow = "attempt to calculate the remainder with overflow",
panic_const_neg_overflow = "attempt to negate with overflow",
panic_const_shr_overflow = "attempt to shift right with overflow",
panic_const_shl_overflow = "attempt to shift left with overflow",
panic_const_div_by_zero = "attempt to divide by zero",
panic_const_rem_by_zero = "attempt to calculate the remainder with a divisor of zero",
}

macro_rules! panic_overflow {
($($lang_unsigned:ident, $lang_signed:ident = $message:tt,)+) => {
$(
#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold)]
#[cfg_attr(panic = "immediate-abort", inline)]
#[track_caller]
#[lang = stringify!($lang_unsigned)]
pub fn $lang_unsigned(_lhs: u128, _rhs: u128) -> ! {
unsafe {
libc::printf($message as *const str as *const i8);
intrinsics::abort()
}
}
#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold)]
#[cfg_attr(panic = "immediate-abort", inline)]
#[track_caller]
#[lang = stringify!($lang_signed)]
pub fn $lang_signed(_lhs: i128, _rhs: i128) -> ! {
unsafe {
libc::printf($message as *const str as *const i8);
intrinsics::abort()
}
}
)+
};
}

panic_overflow! {
panic_add_overflow_unsigned, panic_add_overflow_signed = "attempt to add with overflow",
panic_sub_overflow_unsigned, panic_sub_overflow_signed = "attempt to subtract with overflow",
panic_mul_overflow_unsigned, panic_mul_overflow_signed = "attempt to multiply with overflow",
panic_div_overflow_unsigned, panic_div_overflow_signed = "attempt to divide with overflow",
panic_rem_overflow_unsigned, panic_rem_overflow_signed = "attempt to calculate the remainder with overflow",
panic_shl_overflow_unsigned, panic_shl_overflow_signed = "attempt to shift left with overflow",
panic_shr_overflow_unsigned, panic_shr_overflow_signed = "attempt to shift left right with overflow",
}

#[lang = "panic_bounds_check"]
#[track_caller]
fn panic_bounds_check(index: usize, len: usize) -> ! {
Expand Down
44 changes: 44 additions & 0 deletions compiler/rustc_codegen_cranelift/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,50 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
source_info.span,
)
}
AssertKind::Overflow(binop, lhs, rhs) => {
let tcx = fx.tcx;
let is_signed = lhs.ty(fx.mir, tcx).is_signed();

use rustc_hir::LangItem::*;
let lang = match (binop, is_signed) {
(mir::BinOp::Add, true) => PanicAddOverflowSigned,
(mir::BinOp::Add, false) => PanicAddOverflowUnsigned,
(mir::BinOp::Sub, true) => PanicSubOverflowSigned,
(mir::BinOp::Sub, false) => PanicSubOverflowUnsigned,
(mir::BinOp::Mul, true) => PanicMulOverflowSigned,
(mir::BinOp::Mul, false) => PanicMulOverflowUnsigned,
(mir::BinOp::Div, true) => PanicDivOverflowSigned,
(mir::BinOp::Div, false) => PanicDivOverflowUnsigned,
(mir::BinOp::Rem, true) => PanicRemOverflowSigned,
(mir::BinOp::Rem, false) => PanicRemOverflowUnsigned,
(mir::BinOp::Shl, true) => PanicShlOverflowSigned,
(mir::BinOp::Shl, false) => PanicShlOverflowUnsigned,
(mir::BinOp::Shr, true) => PanicShrOverflowSigned,
(mir::BinOp::Shr, false) => PanicShrOverflowUnsigned,
_ => bug!("binop {:?} should not have overflow assert", binop),
};

let lhs = codegen_operand(fx, lhs).load_scalar(fx);
let rhs = codegen_operand(fx, rhs).load_scalar(fx);

let i128_ty = tcx.types.i128;
let clif_128_ty = fx.clif_type(i128_ty).unwrap();

let lhs =
clif_int_or_float_cast(fx, lhs, is_signed, clif_128_ty, is_signed);
let rhs =
clif_int_or_float_cast(fx, rhs, is_signed, clif_128_ty, is_signed);

let location = fx.get_caller_location(source_info).load_scalar(fx);

codegen_panic_inner(
fx,
lang,
&[lhs, rhs, location],
*unwind,
source_info.span,
)
}
_ => {
let location = fx.get_caller_location(source_info).load_scalar(fx);

Expand Down
44 changes: 37 additions & 7 deletions compiler/rustc_codegen_gcc/example/mini_core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -505,18 +505,48 @@ macro_rules! panic_const {
}

panic_const! {
panic_const_add_overflow = "attempt to add with overflow",
panic_const_sub_overflow = "attempt to subtract with overflow",
panic_const_mul_overflow = "attempt to multiply with overflow",
panic_const_div_overflow = "attempt to divide with overflow",
panic_const_rem_overflow = "attempt to calculate the remainder with overflow",
panic_const_neg_overflow = "attempt to negate with overflow",
panic_const_shr_overflow = "attempt to shift right with overflow",
panic_const_shl_overflow = "attempt to shift left with overflow",
panic_const_div_by_zero = "attempt to divide by zero",
panic_const_rem_by_zero = "attempt to calculate the remainder with a divisor of zero",
}

macro_rules! panic_overflow {
($($lang_unsigned:ident, $lang_signed:ident = $message:tt,)+) => {
$(
#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold)]
#[cfg_attr(panic = "immediate-abort", inline)]
#[track_caller]
#[lang = stringify!($lang_unsigned)]
pub fn $lang_unsigned(_lhs: u128, _rhs: u128) -> ! {
unsafe {
libc::printf($message as *const str as *const i8);
intrinsics::abort()
}
}
#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold)]
#[cfg_attr(panic = "immediate-abort", inline)]
#[track_caller]
#[lang = stringify!($lang_signed)]
pub fn $lang_signed(_lhs: i128, _rhs: i128) -> ! {
unsafe {
libc::printf($message as *const str as *const i8);
intrinsics::abort()
}
}
)+
};
}

panic_overflow! {
panic_add_overflow_unsigned, panic_add_overflow_signed = "attempt to add with overflow",
panic_sub_overflow_unsigned, panic_sub_overflow_signed = "attempt to subtract with overflow",
panic_mul_overflow_unsigned, panic_mul_overflow_signed = "attempt to multiply with overflow",
panic_div_overflow_unsigned, panic_div_overflow_signed = "attempt to divide with overflow",
panic_rem_overflow_unsigned, panic_rem_overflow_signed = "attempt to calculate the remainder with overflow",
panic_shl_overflow_unsigned, panic_shl_overflow_signed = "attempt to shift left with overflow",
panic_shr_overflow_unsigned, panic_shr_overflow_signed = "attempt to shift left right with overflow",
}

#[lang = "panic_cannot_unwind"]
fn panic_cannot_unwind() -> ! {
unsafe {
Expand Down
74 changes: 62 additions & 12 deletions compiler/rustc_codegen_ssa/src/mir/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -740,40 +740,90 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let location = self.get_caller_location(bx, terminator.source_info).immediate();

// Put together the arguments to the panic entry point.
let (lang_item, args) = match msg {
let ((fn_abi, llfn, instance), args) = match msg {
AssertKind::BoundsCheck { len, index } => {
let len = self.codegen_operand(bx, len).immediate();
let index = self.codegen_operand(bx, index).immediate();
// It's `fn panic_bounds_check(index: usize, len: usize)`,
// and `#[track_caller]` adds an implicit third argument.
(LangItem::PanicBoundsCheck, vec![index, len, location])
(
common::build_langcall(bx, span, LangItem::PanicBoundsCheck),
vec![index, len, location],
)
}
AssertKind::MisalignedPointerDereference { required, found } => {
let required = self.codegen_operand(bx, required).immediate();
let found = self.codegen_operand(bx, found).immediate();
// It's `fn panic_misaligned_pointer_dereference(required: usize, found: usize)`,
// and `#[track_caller]` adds an implicit third argument.
(LangItem::PanicMisalignedPointerDereference, vec![required, found, location])
}
AssertKind::NullPointerDereference => {
// It's `fn panic_null_pointer_dereference()`,
// `#[track_caller]` adds an implicit argument.
(LangItem::PanicNullPointerDereference, vec![location])
(
common::build_langcall(bx, span, LangItem::PanicMisalignedPointerDereference),
vec![required, found, location],
)
}
AssertKind::InvalidEnumConstruction(source) => {
let source = self.codegen_operand(bx, source).immediate();
// It's `fn panic_invalid_enum_construction(source: u128)`,
// `#[track_caller]` adds an implicit argument.
(LangItem::PanicInvalidEnumConstruction, vec![source, location])
(
common::build_langcall(bx, span, LangItem::PanicInvalidEnumConstruction),
vec![source, location],
)
}
AssertKind::Overflow(binop, lhs, rhs) => {
let tcx = bx.tcx();

let is_signed = lhs.ty(self.mir, tcx).is_signed();

let lang = match (binop, is_signed) {
(mir::BinOp::Add, true) => LangItem::PanicAddOverflowSigned,
(mir::BinOp::Add, false) => LangItem::PanicAddOverflowUnsigned,
(mir::BinOp::Sub, true) => LangItem::PanicSubOverflowSigned,
(mir::BinOp::Sub, false) => LangItem::PanicSubOverflowUnsigned,
(mir::BinOp::Mul, true) => LangItem::PanicMulOverflowSigned,
(mir::BinOp::Mul, false) => LangItem::PanicMulOverflowUnsigned,
(mir::BinOp::Div, true) => LangItem::PanicDivOverflowSigned,
(mir::BinOp::Div, false) => LangItem::PanicDivOverflowUnsigned,
(mir::BinOp::Rem, true) => LangItem::PanicRemOverflowSigned,
(mir::BinOp::Rem, false) => LangItem::PanicRemOverflowUnsigned,
(mir::BinOp::Shl, true) => LangItem::PanicShlOverflowSigned,
(mir::BinOp::Shl, false) => LangItem::PanicShlOverflowUnsigned,
(mir::BinOp::Shr, true) => LangItem::PanicShrOverflowSigned,
(mir::BinOp::Shr, false) => LangItem::PanicShrOverflowUnsigned,
_ => bug!("binop {:?} should not have overflow assert", binop),
};

let (lhs, rhs) = if is_signed {
let i128_ty = tcx.types.i128;
let i128_llty = bx.immediate_backend_type(bx.layout_of(i128_ty));

let lhs = self.codegen_operand(bx, lhs).immediate();
let lhs = bx.sext(lhs, i128_llty);
let rhs = self.codegen_operand(bx, rhs).immediate();
let rhs = bx.sext(rhs, i128_llty);

(lhs, rhs)
} else {
let u128_ty = tcx.types.u128;
let u128_llty = bx.immediate_backend_type(bx.layout_of(u128_ty));

let lhs = self.codegen_operand(bx, lhs).immediate();
let lhs = bx.zext(lhs, u128_llty);
let rhs = self.codegen_operand(bx, rhs).immediate();
let rhs = bx.zext(rhs, u128_llty);

(lhs, rhs)
};

// signature fn(lhs, rhs), plus #[track_caller] location
(common::build_langcall(bx, span, lang), vec![lhs, rhs, location])
}
_ => {
// It's `pub fn panic_...()` and `#[track_caller]` adds an implicit argument.
(msg.panic_function(), vec![location])
(common::build_langcall(bx, span, msg.panic_function()), vec![location])
}
};

let (fn_abi, llfn, instance) = common::build_langcall(bx, span, lang_item);

// Codegen the actual panic invoke/call.
let merging_succ = helper.do_call(
self,
Expand Down
27 changes: 17 additions & 10 deletions compiler/rustc_hir/src/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,16 +289,23 @@ language_item_table! {
PanicCannotUnwind, sym::panic_cannot_unwind, panic_cannot_unwind, Target::Fn, GenericRequirement::Exact(0);
PanicInCleanup, sym::panic_in_cleanup, panic_in_cleanup, Target::Fn, GenericRequirement::Exact(0);
/// Constant panic messages, used for codegen of MIR asserts.
PanicAddOverflow, sym::panic_const_add_overflow, panic_const_add_overflow, Target::Fn, GenericRequirement::None;
PanicSubOverflow, sym::panic_const_sub_overflow, panic_const_sub_overflow, Target::Fn, GenericRequirement::None;
PanicMulOverflow, sym::panic_const_mul_overflow, panic_const_mul_overflow, Target::Fn, GenericRequirement::None;
PanicDivOverflow, sym::panic_const_div_overflow, panic_const_div_overflow, Target::Fn, GenericRequirement::None;
PanicRemOverflow, sym::panic_const_rem_overflow, panic_const_rem_overflow, Target::Fn, GenericRequirement::None;
PanicNegOverflow, sym::panic_const_neg_overflow, panic_const_neg_overflow, Target::Fn, GenericRequirement::None;
PanicShrOverflow, sym::panic_const_shr_overflow, panic_const_shr_overflow, Target::Fn, GenericRequirement::None;
PanicShlOverflow, sym::panic_const_shl_overflow, panic_const_shl_overflow, Target::Fn, GenericRequirement::None;
PanicDivZero, sym::panic_const_div_by_zero, panic_const_div_by_zero, Target::Fn, GenericRequirement::None;
PanicRemZero, sym::panic_const_rem_by_zero, panic_const_rem_by_zero, Target::Fn, GenericRequirement::None;
PanicAddOverflowSigned, sym::panic_add_overflow_signed, panic_add_overflow_signed, Target::Fn, GenericRequirement::None;
PanicAddOverflowUnsigned, sym::panic_add_overflow_unsigned, panic_add_overflow_unsigned, Target::Fn, GenericRequirement::None;
PanicSubOverflowSigned, sym::panic_sub_overflow_signed, panic_sub_overflow_signed, Target::Fn, GenericRequirement::None;
PanicSubOverflowUnsigned, sym::panic_sub_overflow_unsigned, panic_sub_overflow_unsigned, Target::Fn, GenericRequirement::None;
PanicMulOverflowSigned, sym::panic_mul_overflow_signed, panic_mul_overflow_signed, Target::Fn, GenericRequirement::None;
PanicMulOverflowUnsigned, sym::panic_mul_overflow_unsigned, panic_mul_overflow_unsigned, Target::Fn, GenericRequirement::None;
PanicDivOverflowSigned, sym::panic_div_overflow_signed, panic_div_overflow_signed, Target::Fn, GenericRequirement::None;
PanicDivOverflowUnsigned, sym::panic_div_overflow_unsigned, panic_div_overflow_unsigned, Target::Fn, GenericRequirement::None;
PanicRemOverflowSigned, sym::panic_rem_overflow_signed, panic_rem_overflow_signed, Target::Fn, GenericRequirement::None;
PanicRemOverflowUnsigned, sym::panic_rem_overflow_unsigned, panic_rem_overflow_unsigned, Target::Fn, GenericRequirement::None;
PanicShlOverflowSigned, sym::panic_shl_overflow_signed, panic_shl_overflow_signed, Target::Fn, GenericRequirement::None;
PanicShlOverflowUnsigned, sym::panic_shl_overflow_unsigned, panic_shl_overflow_unsigned, Target::Fn, GenericRequirement::None;
PanicShrOverflowSigned, sym::panic_shr_overflow_signed, panic_shr_overflow_signed, Target::Fn, GenericRequirement::None;
PanicShrOverflowUnsigned, sym::panic_shr_overflow_unsigned, panic_shr_overflow_unsigned, Target::Fn, GenericRequirement::None;
PanicNegOverflow, sym::panic_const_neg_overflow, panic_const_neg_overflow, Target::Fn, GenericRequirement::None;
PanicDivZero, sym::panic_const_div_by_zero, panic_const_div_by_zero, Target::Fn, GenericRequirement::None;
PanicRemZero, sym::panic_const_rem_by_zero, panic_const_rem_by_zero, Target::Fn, GenericRequirement::None;
PanicCoroutineResumed, sym::panic_const_coroutine_resumed, panic_const_coroutine_resumed, Target::Fn, GenericRequirement::None;
PanicAsyncFnResumed, sym::panic_const_async_fn_resumed, panic_const_async_fn_resumed, Target::Fn, GenericRequirement::None;
PanicAsyncGenFnResumed, sym::panic_const_async_gen_fn_resumed, panic_const_async_gen_fn_resumed, Target::Fn, GenericRequirement::None;
Expand Down
20 changes: 12 additions & 8 deletions compiler/rustc_middle/src/mir/terminator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,15 +176,19 @@
pub fn panic_function(&self) -> LangItem {
use AssertKind::*;
match self {
Overflow(BinOp::Add, _, _) => LangItem::PanicAddOverflow,
Overflow(BinOp::Sub, _, _) => LangItem::PanicSubOverflow,
Overflow(BinOp::Mul, _, _) => LangItem::PanicMulOverflow,
Overflow(BinOp::Div, _, _) => LangItem::PanicDivOverflow,
Overflow(BinOp::Rem, _, _) => LangItem::PanicRemOverflow,
OverflowNeg(_) => LangItem::PanicNegOverflow,
Overflow(BinOp::Shr, _, _) => LangItem::PanicShrOverflow,
Overflow(BinOp::Shl, _, _) => LangItem::PanicShlOverflow,
Overflow(
BinOp::Add
| BinOp::Sub
| BinOp::Mul
| BinOp::Div
| BinOp::Rem
| BinOp::Shr
| BinOp::Shl,
_,
_,
) => bug!("Binops handled elsewhere"),

Check failure on line 189 in compiler/rustc_middle/src/mir/terminator.rs

View workflow job for this annotation

GitHub Actions / PR - x86_64-gnu-miri

Binops handled elsewhere

Check failure on line 189 in compiler/rustc_middle/src/mir/terminator.rs

View workflow job for this annotation

GitHub Actions / PR - x86_64-gnu-miri

Binops handled elsewhere

Check failure on line 189 in compiler/rustc_middle/src/mir/terminator.rs

View workflow job for this annotation

GitHub Actions / PR - x86_64-gnu-miri

Binops handled elsewhere

Check failure on line 189 in compiler/rustc_middle/src/mir/terminator.rs

View workflow job for this annotation

GitHub Actions / PR - x86_64-gnu-miri

Binops handled elsewhere

Check failure on line 189 in compiler/rustc_middle/src/mir/terminator.rs

View workflow job for this annotation

GitHub Actions / PR - x86_64-gnu-miri

Binops handled elsewhere

Check failure on line 189 in compiler/rustc_middle/src/mir/terminator.rs

View workflow job for this annotation

GitHub Actions / PR - x86_64-gnu-miri

Binops handled elsewhere
Overflow(op, _, _) => bug!("{:?} cannot overflow", op),
OverflowNeg(_) => LangItem::PanicNegOverflow,
DivisionByZero(_) => LangItem::PanicDivZero,
RemainderByZero(_) => LangItem::PanicRemZero,
ResumedAfterReturn(CoroutineKind::Coroutine(_)) => LangItem::PanicCoroutineResumed,
Expand Down
Loading
Loading