Auto merge of #127995 - workingjubilee:say-turings-prayer, r=BoxyUwU
compiler: Never debug_assert in codegen In the name of Turing and his Hoarey heralds, assert our truths before creating a monster! The `rustc_codegen_llvm` and `rustc_codegen_ssa` crates are fairly critical for rustc's correctness. Small mistakes here can easily result in undefined behavior, since a "small mistake" can mean something like "link and execute the wrong code". We should probably run any and all asserts in these modules unconditionally on whether this is a "debug build", and damn the costs in performance. ...Especially because the costs in performance seem to be *nothing*. It is not clear how much correctness we gain here, but I'll take free correctness improvements.
This commit is contained in:
commit
28e684b470
16 changed files with 57 additions and 65 deletions
|
@ -84,7 +84,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
|
|||
}
|
||||
if is_cleanupret {
|
||||
// Cross-funclet jump - need a trampoline
|
||||
debug_assert!(base::wants_new_eh_instructions(fx.cx.tcx().sess));
|
||||
assert!(base::wants_new_eh_instructions(fx.cx.tcx().sess));
|
||||
debug!("llbb_with_cleanup: creating cleanup trampoline for {:?}", target);
|
||||
let name = &format!("{:?}_cleanup_trampoline_{:?}", self.bb, target);
|
||||
let trampoline_llbb = Bx::append_block(fx.cx, fx.llfn, name);
|
||||
|
|
|
@ -194,7 +194,7 @@ fn calculate_debuginfo_offset<
|
|||
}
|
||||
_ => {
|
||||
// Sanity check for `can_use_in_debuginfo`.
|
||||
debug_assert!(!elem.can_use_in_debuginfo());
|
||||
assert!(!elem.can_use_in_debuginfo());
|
||||
bug!("unsupported var debuginfo projection `{:?}`", projection)
|
||||
}
|
||||
}
|
||||
|
@ -502,7 +502,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
|
||||
let DebugInfoOffset { direct_offset, indirect_offsets, result: fragment_layout } =
|
||||
calculate_debuginfo_offset(bx, &fragment.projection, var_layout);
|
||||
debug_assert!(indirect_offsets.is_empty());
|
||||
assert!(indirect_offsets.is_empty());
|
||||
|
||||
if fragment_layout.size == Size::ZERO {
|
||||
// Fragment is a ZST, so does not represent anything. Avoid generating anything
|
||||
|
|
|
@ -565,7 +565,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
for elem in place_ref.projection.iter() {
|
||||
match elem {
|
||||
mir::ProjectionElem::Field(ref f, _) => {
|
||||
debug_assert!(
|
||||
assert!(
|
||||
!o.layout.ty.is_any_ptr(),
|
||||
"Bad PlaceRef: destructing pointers should use cast/PtrMetadata, \
|
||||
but tried to access field {f:?} of pointer {o:?}",
|
||||
|
|
|
@ -55,7 +55,7 @@ impl<V: CodegenObject> PlaceValue<V> {
|
|||
|
||||
/// Creates a `PlaceRef` to this location with the given type.
|
||||
pub fn with_type<'tcx>(self, layout: TyAndLayout<'tcx>) -> PlaceRef<'tcx, V> {
|
||||
debug_assert!(
|
||||
assert!(
|
||||
layout.is_unsized() || layout.abi.is_uninhabited() || self.llextra.is_none(),
|
||||
"Had pointer metadata {:?} for sized type {layout:?}",
|
||||
self.llextra,
|
||||
|
@ -488,7 +488,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
cg_base = match *elem {
|
||||
mir::ProjectionElem::Deref => bx.load_operand(cg_base).deref(bx.cx()),
|
||||
mir::ProjectionElem::Field(ref field, _) => {
|
||||
debug_assert!(
|
||||
assert!(
|
||||
!cg_base.layout.ty.is_any_ptr(),
|
||||
"Bad PlaceRef: destructing pointers should use cast/PtrMetadata, \
|
||||
but tried to access field {field:?} of pointer {cg_base:?}",
|
||||
|
|
|
@ -168,8 +168,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
dst: PlaceRef<'tcx, Bx::Value>,
|
||||
) {
|
||||
// The MIR validator enforces no unsized transmutes.
|
||||
debug_assert!(src.layout.is_sized());
|
||||
debug_assert!(dst.layout.is_sized());
|
||||
assert!(src.layout.is_sized());
|
||||
assert!(dst.layout.is_sized());
|
||||
|
||||
if let Some(val) = self.codegen_transmute_operand(bx, src, dst.layout) {
|
||||
val.store(bx, dst);
|
||||
|
@ -223,8 +223,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
|
||||
match operand.val {
|
||||
OperandValue::Ref(source_place_val) => {
|
||||
debug_assert_eq!(source_place_val.llextra, None);
|
||||
debug_assert!(matches!(operand_kind, OperandValueKind::Ref));
|
||||
assert_eq!(source_place_val.llextra, None);
|
||||
assert!(matches!(operand_kind, OperandValueKind::Ref));
|
||||
Some(bx.load_operand(source_place_val.with_type(cast)).val)
|
||||
}
|
||||
OperandValue::ZeroSized => {
|
||||
|
@ -295,7 +295,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
to_scalar: abi::Scalar,
|
||||
to_backend_ty: Bx::Type,
|
||||
) -> Bx::Value {
|
||||
debug_assert_eq!(from_scalar.size(self.cx), to_scalar.size(self.cx));
|
||||
assert_eq!(from_scalar.size(self.cx), to_scalar.size(self.cx));
|
||||
|
||||
use abi::Primitive::*;
|
||||
imm = bx.from_immediate(imm);
|
||||
|
@ -639,9 +639,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
(OperandValue::Immediate(llval), operand.layout)
|
||||
}
|
||||
mir::UnOp::PtrMetadata => {
|
||||
debug_assert!(
|
||||
operand.layout.ty.is_unsafe_ptr() || operand.layout.ty.is_ref(),
|
||||
);
|
||||
assert!(operand.layout.ty.is_unsafe_ptr() || operand.layout.ty.is_ref(),);
|
||||
let (_, meta) = operand.val.pointer_parts();
|
||||
assert_eq!(operand.layout.fields.count() > 1, meta.is_some());
|
||||
if let Some(meta) = meta {
|
||||
|
@ -651,7 +649,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
}
|
||||
}
|
||||
};
|
||||
debug_assert!(
|
||||
assert!(
|
||||
val.is_expected_variant_for_type(self.cx, layout),
|
||||
"Made wrong variant {val:?} for type {layout:?}",
|
||||
);
|
||||
|
@ -742,7 +740,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
bug!("Field {field_idx:?} is {p:?} making {layout:?}");
|
||||
});
|
||||
let scalars = self.value_kind(op.layout).scalars().unwrap();
|
||||
debug_assert_eq!(values.len(), scalars.len());
|
||||
assert_eq!(values.len(), scalars.len());
|
||||
inputs.extend(values);
|
||||
input_scalars.extend(scalars);
|
||||
}
|
||||
|
@ -760,7 +758,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
);
|
||||
|
||||
let val = OperandValue::from_immediates(inputs);
|
||||
debug_assert!(
|
||||
assert!(
|
||||
val.is_expected_variant_for_type(self.cx, layout),
|
||||
"Made wrong variant {val:?} for type {layout:?}",
|
||||
);
|
||||
|
@ -805,7 +803,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
let val = cg_place.val.address();
|
||||
|
||||
let ty = cg_place.layout.ty;
|
||||
debug_assert!(
|
||||
assert!(
|
||||
if bx.cx().type_has_metadata(ty) {
|
||||
matches!(val, OperandValue::Pair(..))
|
||||
} else {
|
||||
|
@ -927,7 +925,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
}
|
||||
mir::BinOp::Cmp => {
|
||||
use std::cmp::Ordering;
|
||||
debug_assert!(!is_float);
|
||||
assert!(!is_float);
|
||||
let pred = |op| base::bin_op_to_icmp_predicate(op, is_signed);
|
||||
if bx.cx().tcx().sess.opts.optimize == OptLevel::No {
|
||||
// FIXME: This actually generates tighter assembly, and is a classic trick
|
||||
|
@ -1111,7 +1109,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
if layout.is_zst() {
|
||||
OperandValueKind::ZeroSized
|
||||
} else if self.cx.is_backend_immediate(layout) {
|
||||
debug_assert!(!self.cx.is_backend_scalar_pair(layout));
|
||||
assert!(!self.cx.is_backend_scalar_pair(layout));
|
||||
OperandValueKind::Immediate(match layout.abi {
|
||||
abi::Abi::Scalar(s) => s,
|
||||
abi::Abi::Vector { element, .. } => element,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue