From 4c339158da5125dd8151d313e867c43f12171c6d Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Mon, 30 Oct 2023 22:29:32 -0400 Subject: [PATCH] Move alignment checks to codegen --- compiler/rustc_borrowck/src/invalidation.rs | 3 +- compiler/rustc_borrowck/src/lib.rs | 6 +- compiler/rustc_borrowck/src/type_check/mod.rs | 6 +- compiler/rustc_codegen_cranelift/src/base.rs | 46 ++++-- .../rustc_codegen_cranelift/src/constant.rs | 3 +- compiler/rustc_codegen_ssa/src/mir/analyze.rs | 3 +- compiler/rustc_codegen_ssa/src/mir/block.rs | 87 ++++++++++- .../src/const_eval/machine.rs | 6 - .../src/interpret/terminator.rs | 2 +- .../src/transform/check_consts/check.rs | 3 +- .../check_consts/post_drop_elaboration.rs | 3 +- .../src/transform/validate.rs | 5 +- compiler/rustc_middle/messages.ftl | 3 - compiler/rustc_middle/src/mir/pretty.rs | 5 +- compiler/rustc_middle/src/mir/syntax.rs | 24 ++- compiler/rustc_middle/src/mir/terminator.rs | 37 ++--- compiler/rustc_middle/src/mir/visit.rs | 10 +- compiler/rustc_mir_build/src/build/scope.rs | 3 +- compiler/rustc_mir_build/src/lints.rs | 3 +- .../src/impls/borrowed_locals.rs | 3 +- .../src/impls/storage_liveness.rs | 6 +- .../src/move_paths/builder.rs | 1 + .../rustc_mir_dataflow/src/value_analysis.rs | 3 +- .../src/check_alignment.rs | 145 +++--------------- .../rustc_mir_transform/src/check_unsafety.rs | 3 +- .../src/const_prop_lint.rs | 3 +- compiler/rustc_mir_transform/src/coroutine.rs | 6 +- .../rustc_mir_transform/src/coverage/graph.rs | 3 +- .../src/coverage/spans/from_mir.rs | 3 +- compiler/rustc_mir_transform/src/dest_prop.rs | 8 +- compiler/rustc_mir_transform/src/inline.rs | 3 +- .../rustc_mir_transform/src/jump_threading.rs | 2 +- .../src/remove_noop_landing_pads.rs | 3 +- .../src/separate_const_switch.rs | 7 +- compiler/rustc_monomorphize/src/collector.rs | 3 +- compiler/rustc_smir/src/rustc_smir/mod.rs | 7 +- compiler/stable_mir/src/mir/body.rs | 2 +- compiler/stable_mir/src/mir/visit.rs | 5 +- .../clippy_utils/src/qualify_min_const_fn.rs | 3 +- .../ui-fulldeps/stable-mir/check_instance.rs | 9 +- 40 files changed, 252 insertions(+), 234 deletions(-) diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs index ec6d7b74e61a..048157a1560c 100644 --- a/compiler/rustc_borrowck/src/invalidation.rs +++ b/compiler/rustc_borrowck/src/invalidation.rs @@ -205,7 +205,8 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> { | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Unreachable | TerminatorKind::FalseEdge { real_target: _, imaginary_target: _ } - | TerminatorKind::FalseUnwind { real_target: _, unwind: _ } => { + | TerminatorKind::FalseUnwind { real_target: _, unwind: _ } + | TerminatorKind::UbCheck { .. } => { // no data used, thus irrelevant to borrowck } } diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 5787ea13e793..2ff11e8a3b21 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -785,7 +785,8 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro | TerminatorKind::Return | TerminatorKind::CoroutineDrop | TerminatorKind::FalseEdge { real_target: _, imaginary_target: _ } - | TerminatorKind::FalseUnwind { real_target: _, unwind: _ } => { + | TerminatorKind::FalseUnwind { real_target: _, unwind: _ } + | TerminatorKind::UbCheck { .. } => { // no data used, thus irrelevant to borrowck } } @@ -835,7 +836,8 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro | TerminatorKind::Goto { .. } | TerminatorKind::SwitchInt { .. } | TerminatorKind::Unreachable - | TerminatorKind::InlineAsm { .. } => {} + | TerminatorKind::InlineAsm { .. } + | TerminatorKind::UbCheck { .. } => {} } } } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 608d010394f6..ca40cbf0f1c9 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1358,7 +1358,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { | TerminatorKind::Drop { .. } | TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseUnwind { .. } - | TerminatorKind::InlineAsm { .. } => { + | TerminatorKind::InlineAsm { .. } + | TerminatorKind::UbCheck { .. } => { // no checks needed for these } @@ -1690,6 +1691,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup); } + TerminatorKind::UbCheck { target, .. } => { + self.assert_iscleanup(body, block_data, target, is_cleanup) + } } } diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 91b1547cb6ea..af60fb0c7ffa 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -356,18 +356,6 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { source_info.span, ); } - AssertKind::MisalignedPointerDereference { ref required, ref found } => { - let required = codegen_operand(fx, required).load_scalar(fx); - let found = codegen_operand(fx, found).load_scalar(fx); - let location = fx.get_caller_location(source_info).load_scalar(fx); - - codegen_panic_inner( - fx, - rustc_hir::LangItem::PanicMisalignedPointerDereference, - &[required, found, location], - source_info.span, - ); - } _ => { let msg_str = msg.description(); codegen_panic(fx, msg_str, source_info); @@ -488,6 +476,40 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { let target_block = fx.get_block(*target); fx.bcx.ins().jump(target_block, &[]); } + TerminatorKind::UbCheck { target, kind: UbCheckKind::PointerAlignment { pointer } } => { + let location = fx.get_caller_location(source_info).load_scalar(fx); + let pointer = codegen_operand(fx, pointer); + let pointee_ty = pointer.layout().ty.builtin_deref(true).unwrap(); + let pointee_layout = fx.layout_of(pointee_ty.ty); + let pointer = pointer.load_scalar(fx); + + // Compute the alignment mask + let align = pointee_layout.align.abi.bytes() as i64; + let mask = fx.bcx.ins().iconst(fx.pointer_type, align - 1); + let required = fx.bcx.ins().iconst(fx.pointer_type, align); + + // And the pointer with the mask + let masked = fx.bcx.ins().band(pointer, mask); + + // Branch on whether the masked value is zero + let is_zero = fx.bcx.ins().icmp_imm(IntCC::Equal, masked, 0); + + // Create a new block that we will jump to if !is_zero + let failure = fx.bcx.create_block(); + fx.bcx.set_cold_block(failure); + + let target = fx.get_block(*target); + fx.bcx.ins().brif(is_zero, target, &[], failure, &[]); + + // Codegen the actual panic + fx.bcx.switch_to_block(failure); + codegen_panic_inner( + fx, + rustc_hir::LangItem::PanicMisalignedPointerDereference, + &[required, pointer, location], + source_info.span, + ); + } }; } } diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index b0853d30e03b..7682e63d2872 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -508,7 +508,8 @@ pub(crate) fn mir_operand_get_const_val<'tcx>( | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::Drop { .. } - | TerminatorKind::Assert { .. } => {} + | TerminatorKind::Assert { .. } + | TerminatorKind::UbCheck { .. } => {} TerminatorKind::Yield { .. } | TerminatorKind::CoroutineDrop | TerminatorKind::FalseEdge { .. } diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs index 2285e7f4e01e..a926a02841c5 100644 --- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs +++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs @@ -277,7 +277,8 @@ pub fn cleanup_kinds(mir: &mir::Body<'_>) -> IndexVec { /* nothing to do */ } + | TerminatorKind::FalseUnwind { .. } + | TerminatorKind::UbCheck { .. } => { /* nothing to do */ } TerminatorKind::Call { unwind, .. } | TerminatorKind::InlineAsm { unwind, .. } | TerminatorKind::Assert { unwind, .. } diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 3d2d8f8b5099..951b178d6a9b 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -12,7 +12,7 @@ use crate::MemFlags; use rustc_ast as ast; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_hir::lang_items::LangItem; -use rustc_middle::mir::{self, AssertKind, SwitchTargets, UnwindTerminateReason}; +use rustc_middle::mir::{self, AssertKind, SwitchTargets, UbCheckKind, UnwindTerminateReason}; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement}; use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; use rustc_middle::ty::{self, Instance, Ty}; @@ -616,13 +616,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // and `#[track_caller]` adds an implicit third argument. (LangItem::PanicBoundsCheck, vec![index, len, location]) } - AssertKind::MisalignedPointerDereference { ref required, ref 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]) - } _ => { let msg = bx.const_str(msg.description()); // It's `pub fn panic(expr: &str)`, with the wide reference being passed @@ -736,6 +729,79 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } + fn codegen_alignment_check( + &mut self, + helper: &TerminatorCodegenHelper<'tcx>, + bx: &mut Bx, + pointer: &mir::Operand<'tcx>, + source_info: mir::SourceInfo, + target: mir::BasicBlock, + ) -> MergingSucc { + let span = source_info.span; + let pointer = self.codegen_operand(bx, pointer); + let pointee_ty = pointer.layout.ty.builtin_deref(true).unwrap(); + let pointee_layout = bx.layout_of(pointee_ty.ty); + + let mk_usize = |v: u64| { + let layout = bx.layout_of(bx.tcx().types.usize); + let rustc_target::abi::Abi::Scalar(abi) = layout.abi else { unreachable!() }; + let v = rustc_middle::mir::interpret::Scalar::from_target_usize(v, &bx.tcx()); + bx.scalar_to_backend(v, abi, bx.cx().type_isize()) + }; + + let align = pointee_layout.align.abi.bytes(); + let mask = mk_usize(align - 1); + let zero = mk_usize(0); + let required = mk_usize(align); + + let ptr_imm = match pointer.val { + crate::mir::OperandValue::Immediate(imm) => imm, + crate::mir::OperandValue::Pair(ptr, _) => ptr, + _ => { + unreachable!("{pointer:?}"); + } + }; + let int_imm = bx.ptrtoint(ptr_imm, bx.cx().type_isize()); + + let masked = bx.and(int_imm, mask); + + let is_zero = bx.icmp( + crate::base::bin_op_to_icmp_predicate(mir::BinOp::Eq.to_hir_binop(), false), + masked, + zero, + ); + + let lltarget = helper.llbb_with_cleanup(self, target); + let panic_block = bx.append_sibling_block("panic"); + + bx.cond_br(is_zero, lltarget, panic_block); + + bx.switch_to_block(panic_block); + self.set_debug_loc(bx, source_info); + + let location = self.get_caller_location(bx, source_info).immediate(); + + let found = int_imm; + + let (lang_item, args) = + (LangItem::PanicMisalignedPointerDereference, vec![required, found, location]); + + let (fn_abi, llfn) = common::build_langcall(bx, Some(span), lang_item); + let merging_succ = helper.do_call( + self, + bx, + fn_abi, + llfn, + &args, + None, + mir::UnwindAction::Unreachable, + &[], + false, + ); + assert_eq!(merging_succ, MergingSucc::False); + MergingSucc::False + } + fn codegen_call_terminator( &mut self, helper: TerminatorCodegenHelper<'tcx>, @@ -1291,6 +1357,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.instance, mergeable_succ(), ), + + mir::TerminatorKind::UbCheck { + target, + kind: UbCheckKind::PointerAlignment { ref pointer }, + } => self.codegen_alignment_check(&helper, bx, pointer, terminator.source_info, target), } } diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 4b447229c5f6..2cec9a4db6ec 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -555,12 +555,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, RemainderByZero(op) => RemainderByZero(eval_to_int(op)?), ResumedAfterReturn(coroutine_kind) => ResumedAfterReturn(*coroutine_kind), ResumedAfterPanic(coroutine_kind) => ResumedAfterPanic(*coroutine_kind), - MisalignedPointerDereference { ref required, ref found } => { - MisalignedPointerDereference { - required: eval_to_int(required)?, - found: eval_to_int(found)?, - } - } }; Err(ConstEvalErrKind::AssertFailure(err).into()) } diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index b54c66814563..ceafa503f92b 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -85,7 +85,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.pop_stack_frame(/* unwinding */ false)? } - Goto { target } => self.go_to_block(target), + Goto { target } | UbCheck { target, .. } => self.go_to_block(target), SwitchInt { ref discr, ref targets } => { let discr = self.read_immediate(&self.eval_operand(discr, None)?)?; diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 76116e339859..263cae5bd86e 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -1058,7 +1058,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { | TerminatorKind::UnwindResume | TerminatorKind::Return | TerminatorKind::SwitchInt { .. } - | TerminatorKind::Unreachable => {} + | TerminatorKind::Unreachable + | TerminatorKind::UbCheck { .. } => {} } } } diff --git a/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs b/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs index aff256b3eadd..42c1c2bbf55d 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs @@ -118,7 +118,8 @@ impl<'tcx> Visitor<'tcx> for CheckLiveDrops<'_, 'tcx> { | mir::TerminatorKind::Return | mir::TerminatorKind::SwitchInt { .. } | mir::TerminatorKind::Unreachable - | mir::TerminatorKind::Yield { .. } => {} + | mir::TerminatorKind::Yield { .. } + | mir::TerminatorKind::UbCheck { .. } => {} } } } diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 5922922d47b6..1d95e1d72ea9 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -393,7 +393,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { match &terminator.kind { - TerminatorKind::Goto { target } => { + TerminatorKind::Goto { target } | TerminatorKind::UbCheck { target, .. } => { self.check_edge(location, *target, EdgeKind::Normal); } TerminatorKind::SwitchInt { targets, discr: _ } => { @@ -1298,7 +1298,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { | TerminatorKind::UnwindResume | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return - | TerminatorKind::Unreachable => {} + | TerminatorKind::Unreachable + | TerminatorKind::UbCheck { .. } => {} } self.super_terminator(terminator, location); diff --git a/compiler/rustc_middle/messages.ftl b/compiler/rustc_middle/messages.ftl index 27d555d7e26c..9444f53ce706 100644 --- a/compiler/rustc_middle/messages.ftl +++ b/compiler/rustc_middle/messages.ftl @@ -14,9 +14,6 @@ middle_assert_divide_by_zero = middle_assert_gen_resume_after_panic = `gen` fn or block cannot be further iterated on after it panicked -middle_assert_misaligned_ptr_deref = - misaligned pointer dereference: address must be a multiple of {$required} but is {$found} - middle_assert_op_overflow = attempt to compute `{$left} {$op} {$right}`, which would overflow diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index a1324858416a..88d549ffafe6 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -858,6 +858,9 @@ impl<'tcx> TerminatorKind<'tcx> { } write!(fmt, ", options({options:?}))") } + UbCheck { target: _, kind: UbCheckKind::PointerAlignment { pointer } } => { + write!(fmt, "pointer_alignment_check({pointer:?})") + } } } @@ -866,7 +869,7 @@ impl<'tcx> TerminatorKind<'tcx> { use self::TerminatorKind::*; match *self { Return | UnwindResume | UnwindTerminate(_) | Unreachable | CoroutineDrop => vec![], - Goto { .. } => vec!["".into()], + Goto { .. } | UbCheck { .. } => vec!["".into()], SwitchInt { ref targets, .. } => targets .values .iter() diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 7b0f27f9b348..e6fb91a1400d 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -588,7 +588,9 @@ impl CallSource { #[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, TypeFoldable, TypeVisitable)] pub enum TerminatorKind<'tcx> { /// Block has one successor; we continue execution there. - Goto { target: BasicBlock }, + Goto { + target: BasicBlock, + }, /// Switches based on the computed value. /// @@ -655,7 +657,12 @@ pub enum TerminatorKind<'tcx> { /// The `replace` flag indicates whether this terminator was created as part of an assignment. /// This should only be used for diagnostic purposes, and does not have any operational /// meaning. - Drop { place: Place<'tcx>, target: BasicBlock, unwind: UnwindAction, replace: bool }, + Drop { + place: Place<'tcx>, + target: BasicBlock, + unwind: UnwindAction, + replace: bool, + }, /// Roughly speaking, evaluates the `func` operand and the arguments, and starts execution of /// the referred to function. The operand types must match the argument types of the function. @@ -798,6 +805,17 @@ pub enum TerminatorKind<'tcx> { /// if and only if InlineAsmOptions::MAY_UNWIND is set. unwind: UnwindAction, }, + + UbCheck { + target: BasicBlock, + kind: UbCheckKind<'tcx>, + }, +} + +#[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, TypeFoldable, TypeVisitable)] +#[derive(Debug)] +pub enum UbCheckKind<'tcx> { + PointerAlignment { pointer: Operand<'tcx> }, } impl TerminatorKind<'_> { @@ -819,6 +837,7 @@ impl TerminatorKind<'_> { TerminatorKind::FalseEdge { .. } => "FalseEdge", TerminatorKind::FalseUnwind { .. } => "FalseUnwind", TerminatorKind::InlineAsm { .. } => "InlineAsm", + TerminatorKind::UbCheck { .. } => "UbCheck", } } } @@ -885,7 +904,6 @@ pub enum AssertKind { RemainderByZero(O), ResumedAfterReturn(CoroutineKind), ResumedAfterPanic(CoroutineKind), - MisalignedPointerDereference { required: O, found: O }, } #[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)] diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index 9dfbe1733cc5..e1b1c1a98eed 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -129,9 +129,8 @@ impl AssertKind { /// Get the message that is printed at runtime when this assertion fails. /// - /// The caller is expected to handle `BoundsCheck` and `MisalignedPointerDereference` by - /// invoking the appropriate lang item (panic_bounds_check/panic_misaligned_pointer_dereference) - /// instead of printing a static message. + /// The caller is expected to handle `BoundsCheck` by invoking the appropriate + /// lang item (panic_bounds_check) instead of printing a static message. pub fn description(&self) -> &'static str { use AssertKind::*; match self { @@ -157,7 +156,7 @@ impl AssertKind { "`gen fn` should just keep returning `None` after panicking" } - BoundsCheck { .. } | MisalignedPointerDereference { .. } => { + BoundsCheck { .. } => { bug!("Unexpected AssertKind") } } @@ -214,12 +213,6 @@ impl AssertKind { Overflow(BinOp::Shl, _, r) => { write!(f, "\"attempt to shift left by `{{}}`, which would overflow\", {r:?}") } - MisalignedPointerDereference { required, found } => { - write!( - f, - "\"misaligned pointer dereference: address must be a multiple of {{}} but is {{}}\", {required:?}, {found:?}" - ) - } _ => write!(f, "\"{}\"", self.description()), } } @@ -254,8 +247,6 @@ impl AssertKind { ResumedAfterPanic(CoroutineKind::Coroutine) => { middle_assert_coroutine_resume_after_panic } - - MisalignedPointerDereference { .. } => middle_assert_misaligned_ptr_deref, } } @@ -288,10 +279,6 @@ impl AssertKind { add!("right", format!("{right:#?}")); } ResumedAfterReturn(_) | ResumedAfterPanic(_) => {} - MisalignedPointerDereference { required, found } => { - add!("required", format!("{required:#?}")); - add!("found", format!("{found:#?}")); - } } } } @@ -348,9 +335,8 @@ impl<'tcx> TerminatorKind<'tcx> { | Assert { target: t, unwind: _, .. } | FalseUnwind { real_target: t, unwind: _ } | InlineAsm { destination: None, unwind: UnwindAction::Cleanup(t), .. } - | InlineAsm { destination: Some(t), unwind: _, .. } => { - Some(t).into_iter().chain((&[]).into_iter().copied()) - } + | InlineAsm { destination: Some(t), unwind: _, .. } + | UbCheck { target: t, .. } => Some(t).into_iter().chain((&[]).into_iter().copied()), UnwindResume | UnwindTerminate(_) | CoroutineDrop @@ -390,9 +376,8 @@ impl<'tcx> TerminatorKind<'tcx> { | Assert { target: ref mut t, unwind: _, .. } | FalseUnwind { real_target: ref mut t, unwind: _ } | InlineAsm { destination: None, unwind: UnwindAction::Cleanup(ref mut t), .. } - | InlineAsm { destination: Some(ref mut t), unwind: _, .. } => { - Some(t).into_iter().chain(&mut []) - } + | InlineAsm { destination: Some(ref mut t), unwind: _, .. } + | UbCheck { target: ref mut t, .. } => Some(t).into_iter().chain(&mut []), UnwindResume | UnwindTerminate(_) | CoroutineDrop @@ -417,7 +402,8 @@ impl<'tcx> TerminatorKind<'tcx> { | TerminatorKind::CoroutineDrop | TerminatorKind::Yield { .. } | TerminatorKind::SwitchInt { .. } - | TerminatorKind::FalseEdge { .. } => None, + | TerminatorKind::FalseEdge { .. } + | TerminatorKind::UbCheck { .. } => None, TerminatorKind::Call { ref unwind, .. } | TerminatorKind::Assert { ref unwind, .. } | TerminatorKind::Drop { ref unwind, .. } @@ -436,7 +422,8 @@ impl<'tcx> TerminatorKind<'tcx> { | TerminatorKind::CoroutineDrop | TerminatorKind::Yield { .. } | TerminatorKind::SwitchInt { .. } - | TerminatorKind::FalseEdge { .. } => None, + | TerminatorKind::FalseEdge { .. } + | TerminatorKind::UbCheck { .. } => None, TerminatorKind::Call { ref mut unwind, .. } | TerminatorKind::Assert { ref mut unwind, .. } | TerminatorKind::Drop { ref mut unwind, .. } @@ -519,7 +506,7 @@ impl<'tcx> TerminatorKind<'tcx> { TerminatorEdges::None } - Goto { target } => TerminatorEdges::Single(target), + Goto { target } | UbCheck { target, .. } => TerminatorEdges::Single(target), Assert { target, unwind, expected: _, msg: _, cond: _ } | Drop { target, unwind, place: _, replace: _ } diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index d47cfd5712f8..c091ac397eb5 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -599,6 +599,12 @@ macro_rules! make_mir_visitor { } } } + TerminatorKind::UbCheck { + kind: UbCheckKind::PointerAlignment { pointer }, + target: _, + } => { + self.visit_operand(pointer, location) + } } } @@ -621,10 +627,6 @@ macro_rules! make_mir_visitor { ResumedAfterReturn(_) | ResumedAfterPanic(_) => { // Nothing to visit } - MisalignedPointerDereference { required, found } => { - self.visit_operand(required, location); - self.visit_operand(found, location); - } } } diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs index b3d3863b5db7..1f7dadaf4b25 100644 --- a/compiler/rustc_mir_build/src/build/scope.rs +++ b/compiler/rustc_mir_build/src/build/scope.rs @@ -1512,7 +1512,8 @@ impl<'tcx> DropTreeBuilder<'tcx> for Unwind { | TerminatorKind::Unreachable | TerminatorKind::Yield { .. } | TerminatorKind::CoroutineDrop - | TerminatorKind::FalseEdge { .. } => { + | TerminatorKind::FalseEdge { .. } + | TerminatorKind::UbCheck { .. } => { span_bug!(term.source_info.span, "cannot unwind from {:?}", term.kind) } } diff --git a/compiler/rustc_mir_build/src/lints.rs b/compiler/rustc_mir_build/src/lints.rs index acf4d6bc2a07..a29a7faa4c03 100644 --- a/compiler/rustc_mir_build/src/lints.rs +++ b/compiler/rustc_mir_build/src/lints.rs @@ -214,7 +214,8 @@ impl<'mir, 'tcx, C: TerminatorClassifier<'tcx>> TriColorVisitor ControlFlow::Continue(()), + | TerminatorKind::SwitchInt { .. } + | TerminatorKind::UbCheck { .. } => ControlFlow::Continue(()), } } diff --git a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs index 01acc380fa39..70187a7c3dd8 100644 --- a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs +++ b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs @@ -148,7 +148,8 @@ where | TerminatorKind::Return | TerminatorKind::SwitchInt { .. } | TerminatorKind::Unreachable - | TerminatorKind::Yield { .. } => {} + | TerminatorKind::Yield { .. } + | TerminatorKind::UbCheck { .. } => {} } } } diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs index 5a58e3af8be1..e6065648ca0d 100644 --- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs @@ -301,7 +301,8 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, '_, 'tcx> { | TerminatorKind::UnwindResume | TerminatorKind::Return | TerminatorKind::SwitchInt { .. } - | TerminatorKind::Unreachable => {} + | TerminatorKind::Unreachable + | TerminatorKind::UbCheck { .. } => {} } } @@ -338,7 +339,8 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, '_, 'tcx> { | TerminatorKind::UnwindResume | TerminatorKind::Return | TerminatorKind::SwitchInt { .. } - | TerminatorKind::Unreachable => {} + | TerminatorKind::Unreachable + | TerminatorKind::UbCheck { .. } => {} } self.check_for_move(trans, loc); diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index ccf3dc7941fe..dab59086df4a 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -432,6 +432,7 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { fn gather_terminator(&mut self, term: &Terminator<'tcx>) { match term.kind { TerminatorKind::Goto { target: _ } + | TerminatorKind::UbCheck { .. } | TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseUnwind { .. } // In some sense returning moves the return place into the current diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 025d2ddfd4ff..8a095ecd8bf8 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -276,7 +276,8 @@ pub trait ValueAnalysis<'tcx> { | TerminatorKind::Assert { .. } | TerminatorKind::CoroutineDrop | TerminatorKind::FalseEdge { .. } - | TerminatorKind::FalseUnwind { .. } => { + | TerminatorKind::FalseUnwind { .. } + | TerminatorKind::UbCheck { .. } => { // These terminators have no effect on the analysis. } } diff --git a/compiler/rustc_mir_transform/src/check_alignment.rs b/compiler/rustc_mir_transform/src/check_alignment.rs index 42b2f18869c2..ef8cf8772983 100644 --- a/compiler/rustc_mir_transform/src/check_alignment.rs +++ b/compiler/rustc_mir_transform/src/check_alignment.rs @@ -1,12 +1,10 @@ use crate::MirPass; use rustc_hir::lang_items::LangItem; use rustc_index::IndexVec; +use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; -use rustc_middle::mir::{ - interpret::Scalar, - visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor}, -}; -use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, TypeAndMut}; +use rustc_middle::ty; +use rustc_middle::ty::TyCtxt; use rustc_session::Session; pub struct CheckAlignment; @@ -29,7 +27,6 @@ impl<'tcx> MirPass<'tcx> for CheckAlignment { let basic_blocks = body.basic_blocks.as_mut(); let local_decls = &mut body.local_decls; - let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); // This pass inserts new blocks. Each insertion changes the Location for all // statements/blocks after. Iterating or visiting the MIR in order would require updating @@ -42,22 +39,18 @@ impl<'tcx> MirPass<'tcx> for CheckAlignment { let statement = &basic_blocks[block].statements[statement_index]; let source_info = statement.source_info; - let mut finder = - PointerFinder { tcx, local_decls, param_env, pointers: Vec::new() }; + let mut finder = PointerFinder { local_decls, tcx, pointers: Vec::new() }; finder.visit_statement(statement, location); - - for (local, ty) in finder.pointers { - debug!("Inserting alignment check for {:?}", ty); + for pointer in finder.pointers { + debug!("Inserting alignment check for {:?}", pointer.ty(&*local_decls, tcx).ty); let new_block = split_block(basic_blocks, location); - insert_alignment_check( - tcx, - local_decls, - &mut basic_blocks[block], - local, - ty, + basic_blocks[block].terminator = Some(Terminator { source_info, - new_block, - ); + kind: TerminatorKind::UbCheck { + target: new_block, + kind: UbCheckKind::PointerAlignment { pointer: Operand::Copy(pointer) }, + }, + }); } } } @@ -66,9 +59,8 @@ impl<'tcx> MirPass<'tcx> for CheckAlignment { struct PointerFinder<'tcx, 'a> { tcx: TyCtxt<'tcx>, - local_decls: &'a mut LocalDecls<'tcx>, - param_env: ParamEnv<'tcx>, - pointers: Vec<(Place<'tcx>, Ty<'tcx>)>, + local_decls: &'a LocalDecls<'tcx>, + pointers: Vec>, } impl<'tcx, 'a> Visitor<'tcx> for PointerFinder<'tcx, 'a> { @@ -108,11 +100,6 @@ impl<'tcx, 'a> Visitor<'tcx> for PointerFinder<'tcx, 'a> { let pointee_ty = pointer_ty.builtin_deref(true).expect("no builtin_deref for an unsafe pointer").ty; - // Ideally we'd support this in the future, but for now we are limited to sized types. - if !pointee_ty.is_sized(self.tcx, self.param_env) { - debug!("Unsafe pointer, but pointee is not known to be sized: {:?}", pointer_ty); - return; - } // Try to detect types we are sure have an alignment of 1 and skip the check // We don't need to look for str and slices, we already rejected unsized types above @@ -120,13 +107,16 @@ impl<'tcx, 'a> Visitor<'tcx> for PointerFinder<'tcx, 'a> { ty::Array(ty, _) => *ty, _ => pointee_ty, }; - if [self.tcx.types.bool, self.tcx.types.i8, self.tcx.types.u8].contains(&element_ty) { + + if [self.tcx.types.bool, self.tcx.types.i8, self.tcx.types.u8, self.tcx.types.str_] + .contains(&element_ty) + { debug!("Trivially aligned place type: {:?}", pointee_ty); return; } // Ensure that this place is based on an aligned pointer. - self.pointers.push((pointer, pointee_ty)); + self.pointers.push(pointer); self.super_place(place, context, location); } @@ -147,100 +137,3 @@ fn split_block( basic_blocks.push(new_block) } - -fn insert_alignment_check<'tcx>( - tcx: TyCtxt<'tcx>, - local_decls: &mut IndexVec>, - block_data: &mut BasicBlockData<'tcx>, - pointer: Place<'tcx>, - pointee_ty: Ty<'tcx>, - source_info: SourceInfo, - new_block: BasicBlock, -) { - // Cast the pointer to a *const () - let const_raw_ptr = Ty::new_ptr(tcx, TypeAndMut { ty: tcx.types.unit, mutbl: Mutability::Not }); - let rvalue = Rvalue::Cast(CastKind::PtrToPtr, Operand::Copy(pointer), const_raw_ptr); - let thin_ptr = local_decls.push(LocalDecl::with_source_info(const_raw_ptr, source_info)).into(); - block_data - .statements - .push(Statement { source_info, kind: StatementKind::Assign(Box::new((thin_ptr, rvalue))) }); - - // Transmute the pointer to a usize (equivalent to `ptr.addr()`) - let rvalue = Rvalue::Cast(CastKind::Transmute, Operand::Copy(thin_ptr), tcx.types.usize); - let addr = local_decls.push(LocalDecl::with_source_info(tcx.types.usize, source_info)).into(); - block_data - .statements - .push(Statement { source_info, kind: StatementKind::Assign(Box::new((addr, rvalue))) }); - - // Get the alignment of the pointee - let alignment = - local_decls.push(LocalDecl::with_source_info(tcx.types.usize, source_info)).into(); - let rvalue = Rvalue::NullaryOp(NullOp::AlignOf, pointee_ty); - block_data.statements.push(Statement { - source_info, - kind: StatementKind::Assign(Box::new((alignment, rvalue))), - }); - - // Subtract 1 from the alignment to get the alignment mask - let alignment_mask = - local_decls.push(LocalDecl::with_source_info(tcx.types.usize, source_info)).into(); - let one = Operand::Constant(Box::new(ConstOperand { - span: source_info.span, - user_ty: None, - const_: Const::Val(ConstValue::Scalar(Scalar::from_target_usize(1, &tcx)), tcx.types.usize), - })); - block_data.statements.push(Statement { - source_info, - kind: StatementKind::Assign(Box::new(( - alignment_mask, - Rvalue::BinaryOp(BinOp::Sub, Box::new((Operand::Copy(alignment), one))), - ))), - }); - - // BitAnd the alignment mask with the pointer - let alignment_bits = - local_decls.push(LocalDecl::with_source_info(tcx.types.usize, source_info)).into(); - block_data.statements.push(Statement { - source_info, - kind: StatementKind::Assign(Box::new(( - alignment_bits, - Rvalue::BinaryOp( - BinOp::BitAnd, - Box::new((Operand::Copy(addr), Operand::Copy(alignment_mask))), - ), - ))), - }); - - // Check if the alignment bits are all zero - let is_ok = local_decls.push(LocalDecl::with_source_info(tcx.types.bool, source_info)).into(); - let zero = Operand::Constant(Box::new(ConstOperand { - span: source_info.span, - user_ty: None, - const_: Const::Val(ConstValue::Scalar(Scalar::from_target_usize(0, &tcx)), tcx.types.usize), - })); - block_data.statements.push(Statement { - source_info, - kind: StatementKind::Assign(Box::new(( - is_ok, - Rvalue::BinaryOp(BinOp::Eq, Box::new((Operand::Copy(alignment_bits), zero.clone()))), - ))), - }); - - // Set this block's terminator to our assert, continuing to new_block if we pass - block_data.terminator = Some(Terminator { - source_info, - kind: TerminatorKind::Assert { - cond: Operand::Copy(is_ok), - expected: true, - target: new_block, - msg: Box::new(AssertKind::MisalignedPointerDereference { - required: Operand::Copy(alignment), - found: Operand::Copy(addr), - }), - // This calls panic_misaligned_pointer_dereference, which is #[rustc_nounwind]. - // We never want to insert an unwind into unsafe code, because unwinding could - // make a failing UB check turn into much worse UB when we start unwinding. - unwind: UnwindAction::Unreachable, - }, - }); -} diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs index 8872f9a97d74..ca28fee121ed 100644 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ b/compiler/rustc_mir_transform/src/check_unsafety.rs @@ -62,7 +62,8 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> { | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::FalseEdge { .. } - | TerminatorKind::FalseUnwind { .. } => { + | TerminatorKind::FalseUnwind { .. } + | TerminatorKind::UbCheck { .. } => { // safe (at least as emitted during MIR construction) } diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index a23ba9c4aa9f..8f9704e13b7d 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs @@ -652,7 +652,8 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> { | TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseUnwind { .. } | TerminatorKind::Call { .. } - | TerminatorKind::InlineAsm { .. } => {} + | TerminatorKind::InlineAsm { .. } + | TerminatorKind::UbCheck { .. } => {} } self.worklist.extend(terminator.successors()); diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index dfafd8598306..1f44c55b6772 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -1246,7 +1246,8 @@ fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool { | TerminatorKind::Unreachable | TerminatorKind::CoroutineDrop | TerminatorKind::FalseEdge { .. } - | TerminatorKind::FalseUnwind { .. } => {} + | TerminatorKind::FalseUnwind { .. } + | TerminatorKind::UbCheck { .. } => {} // Resume will *continue* unwinding, but if there's no other unwinding terminator it // will never be reached. @@ -1768,7 +1769,8 @@ impl<'tcx> Visitor<'tcx> for EnsureCoroutineFieldAssignmentsNeverAlias<'_> { | TerminatorKind::Assert { .. } | TerminatorKind::CoroutineDrop | TerminatorKind::FalseEdge { .. } - | TerminatorKind::FalseUnwind { .. } => {} + | TerminatorKind::FalseUnwind { .. } + | TerminatorKind::UbCheck { .. } => {} } } } diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs index 6bab62aa8540..ac172ec7f9d6 100644 --- a/compiler/rustc_mir_transform/src/coverage/graph.rs +++ b/compiler/rustc_mir_transform/src/coverage/graph.rs @@ -151,7 +151,8 @@ impl CoverageGraph { | TerminatorKind::Assert { .. } | TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseUnwind { .. } - | TerminatorKind::InlineAsm { .. } => {} + | TerminatorKind::InlineAsm { .. } + | TerminatorKind::UbCheck { .. } => {} } } diff --git a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs index 6189e5379ea0..2dcbf62cedc6 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs @@ -151,7 +151,8 @@ fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option { | TerminatorKind::SwitchInt { .. } // For `FalseEdge`, only the `real` branch is taken, so it is similar to a `Goto`. | TerminatorKind::FalseEdge { .. } - | TerminatorKind::Goto { .. } => None, + | TerminatorKind::Goto { .. } | + TerminatorKind::UbCheck { .. } => None, // Call `func` operand can have a more specific span when part of a chain of calls | TerminatorKind::Call { ref func, .. } => { diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index 15502adfb5aa..54165354fab6 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -142,7 +142,7 @@ use rustc_middle::mir::HasLocalDecls; use rustc_middle::mir::{dump_mir, PassWhere}; use rustc_middle::mir::{ traversal, Body, InlineAsmOperand, Local, LocalKind, Location, Operand, Place, Rvalue, - Statement, StatementKind, TerminatorKind, + Statement, StatementKind, TerminatorKind, UbCheckKind, }; use rustc_middle::ty::TyCtxt; use rustc_mir_dataflow::impls::MaybeLiveLocals; @@ -611,7 +611,11 @@ impl WriteInfo { self.reset(); match terminator { TerminatorKind::SwitchInt { discr: op, .. } - | TerminatorKind::Assert { cond: op, .. } => { + | TerminatorKind::Assert { cond: op, .. } + | TerminatorKind::UbCheck { + target: _, + kind: UbCheckKind::PointerAlignment { pointer: op }, + } => { self.add_operand(op); } TerminatorKind::Call { destination, func, args, .. } => { diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 793dcf0d994c..5c3838d39ba8 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -934,7 +934,8 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> { match terminator.kind { TerminatorKind::CoroutineDrop | TerminatorKind::Yield { .. } => bug!(), - TerminatorKind::Goto { ref mut target } => { + TerminatorKind::Goto { ref mut target } + | TerminatorKind::UbCheck { ref mut target, .. } => { *target = self.map_block(*target); } TerminatorKind::SwitchInt { ref mut targets, .. } => { diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs index 7b918be44741..5394d7ef9f52 100644 --- a/compiler/rustc_mir_transform/src/jump_threading.rs +++ b/compiler/rustc_mir_transform/src/jump_threading.rs @@ -519,7 +519,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { // `SwitchInt` is handled specially. TerminatorKind::SwitchInt { .. } => return, // We can recurse, no thing particular to do. - TerminatorKind::Goto { .. } => None, + TerminatorKind::Goto { .. } | TerminatorKind::UbCheck { .. } => None, // Flood the overwritten place, and progress through. TerminatorKind::Drop { place: destination, .. } | TerminatorKind::Call { destination, .. } => Some(destination), diff --git a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs index 54892442c87b..52a47369ce55 100644 --- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs +++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs @@ -66,7 +66,8 @@ impl RemoveNoopLandingPads { | TerminatorKind::UnwindResume | TerminatorKind::SwitchInt { .. } | TerminatorKind::FalseEdge { .. } - | TerminatorKind::FalseUnwind { .. } => { + | TerminatorKind::FalseUnwind { .. } + | TerminatorKind::UbCheck { .. } => { terminator.successors().all(|succ| nop_landing_pads.contains(succ)) } TerminatorKind::CoroutineDrop diff --git a/compiler/rustc_mir_transform/src/separate_const_switch.rs b/compiler/rustc_mir_transform/src/separate_const_switch.rs index 907cfe7581a8..44c0fc4dd560 100644 --- a/compiler/rustc_mir_transform/src/separate_const_switch.rs +++ b/compiler/rustc_mir_transform/src/separate_const_switch.rs @@ -99,7 +99,9 @@ pub fn separate_const_switch(body: &mut Body<'_>) -> usize { match &predecessor.terminator().kind { // The following terminators are // unconditionally valid - TerminatorKind::Goto { .. } | TerminatorKind::SwitchInt { .. } => {} + TerminatorKind::Goto { .. } + | TerminatorKind::SwitchInt { .. } + | TerminatorKind::UbCheck { .. } => {} TerminatorKind::FalseEdge { real_target, .. } => { if *real_target != block_id { @@ -147,7 +149,8 @@ pub fn separate_const_switch(body: &mut Body<'_>) -> usize { let terminator = blocks[pred_id].terminator_mut(); match terminator.kind { - TerminatorKind::Goto { ref mut target } => { + TerminatorKind::Goto { ref mut target } + | TerminatorKind::UbCheck { ref mut target, .. } => { *target = new_block_id; } diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 65bdcf107622..892d07e5fbf7 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -855,7 +855,8 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> { | mir::TerminatorKind::SwitchInt { .. } | mir::TerminatorKind::UnwindResume | mir::TerminatorKind::Return - | mir::TerminatorKind::Unreachable => {} + | mir::TerminatorKind::Unreachable + | mir::TerminatorKind::UbCheck { .. } => {} mir::TerminatorKind::CoroutineDrop | mir::TerminatorKind::Yield { .. } | mir::TerminatorKind::FalseEdge { .. } diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 27596c08f1c1..e899b6a4bfaa 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -806,12 +806,6 @@ impl<'tcx> Stable<'tcx> for mir::AssertMessage<'tcx> { AssertKind::ResumedAfterPanic(coroutine) => { stable_mir::mir::AssertMessage::ResumedAfterPanic(coroutine.stable(tables)) } - AssertKind::MisalignedPointerDereference { required, found } => { - stable_mir::mir::AssertMessage::MisalignedPointerDereference { - required: required.stable(tables), - found: found.stable(tables), - } - } } } } @@ -1017,6 +1011,7 @@ impl<'tcx> Stable<'tcx> for mir::TerminatorKind<'tcx> { destination: destination.map(|d| d.as_usize()), unwind: unwind.stable(tables), }, + mir::TerminatorKind::UbCheck { .. } => TerminatorKind::UbCheck, mir::TerminatorKind::Yield { .. } | mir::TerminatorKind::CoroutineDrop | mir::TerminatorKind::FalseEdge { .. } diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs index 069337836853..71faf55e215a 100644 --- a/compiler/stable_mir/src/mir/body.rs +++ b/compiler/stable_mir/src/mir/body.rs @@ -120,6 +120,7 @@ pub enum TerminatorKind { destination: Option, unwind: UnwindAction, }, + UbCheck, } #[derive(Clone, Debug, Eq, PartialEq)] @@ -148,7 +149,6 @@ pub enum AssertMessage { RemainderByZero(Operand), ResumedAfterReturn(CoroutineKind), ResumedAfterPanic(CoroutineKind), - MisalignedPointerDereference { required: Operand, found: Operand }, } #[derive(Clone, Debug, Eq, PartialEq)] diff --git a/compiler/stable_mir/src/mir/visit.rs b/compiler/stable_mir/src/mir/visit.rs index 806dced71ff3..d39922e1e608 100644 --- a/compiler/stable_mir/src/mir/visit.rs +++ b/compiler/stable_mir/src/mir/visit.rs @@ -254,6 +254,7 @@ pub trait MirVisitor { TerminatorKind::SwitchInt { discr, targets: _, otherwise: _ } => { self.visit_operand(discr, location); } + TerminatorKind::UbCheck => {} } } @@ -368,10 +369,6 @@ pub trait MirVisitor { } AssertMessage::ResumedAfterReturn(_) | AssertMessage::ResumedAfterPanic(_) => { //nothing to visit } - AssertMessage::MisalignedPointerDereference { required, found } => { - self.visit_operand(required, location); - self.visit_operand(found, location); - } } } } diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index 668ea9fcf3b4..07c8716c037a 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -295,7 +295,8 @@ fn check_terminator<'tcx>( | TerminatorKind::Return | TerminatorKind::UnwindResume | TerminatorKind::UnwindTerminate(_) - | TerminatorKind::Unreachable => Ok(()), + | TerminatorKind::Unreachable | + TerminatorKind::UbCheck { .. } => Ok(()), TerminatorKind::Drop { place, .. } => { if !is_ty_const_destruct(tcx, place.ty(&body.local_decls, tcx).ty, body) { return Err(( diff --git a/tests/ui-fulldeps/stable-mir/check_instance.rs b/tests/ui-fulldeps/stable-mir/check_instance.rs index a340877752d8..1dd79afff3c6 100644 --- a/tests/ui-fulldeps/stable-mir/check_instance.rs +++ b/tests/ui-fulldeps/stable-mir/check_instance.rs @@ -64,9 +64,12 @@ fn test_body(body: mir::Body) { let result = Instance::resolve(def, &args); assert!(result.is_ok()); } - Goto { .. } | Assert { .. } | SwitchInt { .. } | Return | Drop { .. } => { - /* Do nothing */ - } + Goto { .. } + | Assert { .. } + | SwitchInt { .. } + | Return + | Drop { .. } + | UbCheck { .. } => { /* Do nothing */ } _ => { unreachable!("Unexpected terminator {term:?}") }