Skip to content

Commit f6feccf

Browse files
committed
Move alignment checks to codegen
1 parent 98f5ebb commit f6feccf

File tree

37 files changed

+209
-172
lines changed

37 files changed

+209
-172
lines changed

compiler/rustc_borrowck/src/invalidation.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,8 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
205205
| TerminatorKind::UnwindTerminate(_)
206206
| TerminatorKind::Unreachable
207207
| TerminatorKind::FalseEdge { real_target: _, imaginary_target: _ }
208-
| TerminatorKind::FalseUnwind { real_target: _, unwind: _ } => {
208+
| TerminatorKind::FalseUnwind { real_target: _, unwind: _ }
209+
| TerminatorKind::UbCheck { .. } => {
209210
// no data used, thus irrelevant to borrowck
210211
}
211212
}

compiler/rustc_borrowck/src/lib.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -785,7 +785,8 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro
785785
| TerminatorKind::Return
786786
| TerminatorKind::CoroutineDrop
787787
| TerminatorKind::FalseEdge { real_target: _, imaginary_target: _ }
788-
| TerminatorKind::FalseUnwind { real_target: _, unwind: _ } => {
788+
| TerminatorKind::FalseUnwind { real_target: _, unwind: _ }
789+
| TerminatorKind::UbCheck { .. } => {
789790
// no data used, thus irrelevant to borrowck
790791
}
791792
}
@@ -835,7 +836,8 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro
835836
| TerminatorKind::Goto { .. }
836837
| TerminatorKind::SwitchInt { .. }
837838
| TerminatorKind::Unreachable
838-
| TerminatorKind::InlineAsm { .. } => {}
839+
| TerminatorKind::InlineAsm { .. }
840+
| TerminatorKind::UbCheck { .. } => {}
839841
}
840842
}
841843
}

compiler/rustc_borrowck/src/type_check/mod.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -1358,7 +1358,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
13581358
| TerminatorKind::Drop { .. }
13591359
| TerminatorKind::FalseEdge { .. }
13601360
| TerminatorKind::FalseUnwind { .. }
1361-
| TerminatorKind::InlineAsm { .. } => {
1361+
| TerminatorKind::InlineAsm { .. }
1362+
| TerminatorKind::UbCheck { .. } => {
13621363
// no checks needed for these
13631364
}
13641365

@@ -1690,6 +1691,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
16901691
}
16911692
self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup);
16921693
}
1694+
TerminatorKind::UbCheck { target, .. } => {
1695+
self.assert_iscleanup(body, block_data, target, is_cleanup)
1696+
}
16931697
}
16941698
}
16951699

compiler/rustc_codegen_cranelift/src/base.rs

+5
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,11 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
488488
let target_block = fx.get_block(*target);
489489
fx.bcx.ins().jump(target_block, &[]);
490490
}
491+
// FIXME
492+
TerminatorKind::UbCheck { target, .. } => {
493+
let block = fx.get_block(*target);
494+
fx.bcx.ins().jump(block, &[]);
495+
}
491496
};
492497
}
493498
}

compiler/rustc_codegen_cranelift/src/constant.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -508,7 +508,8 @@ pub(crate) fn mir_operand_get_const_val<'tcx>(
508508
| TerminatorKind::Return
509509
| TerminatorKind::Unreachable
510510
| TerminatorKind::Drop { .. }
511-
| TerminatorKind::Assert { .. } => {}
511+
| TerminatorKind::Assert { .. }
512+
| TerminatorKind::UbCheck { .. } => {}
512513
TerminatorKind::Yield { .. }
513514
| TerminatorKind::CoroutineDrop
514515
| TerminatorKind::FalseEdge { .. }

compiler/rustc_codegen_ssa/src/mir/analyze.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,8 @@ pub fn cleanup_kinds(mir: &mir::Body<'_>) -> IndexVec<mir::BasicBlock, CleanupKi
277277
| TerminatorKind::SwitchInt { .. }
278278
| TerminatorKind::Yield { .. }
279279
| TerminatorKind::FalseEdge { .. }
280-
| TerminatorKind::FalseUnwind { .. } => { /* nothing to do */ }
280+
| TerminatorKind::FalseUnwind { .. }
281+
| TerminatorKind::UbCheck { .. } => { /* nothing to do */ }
281282
TerminatorKind::Call { unwind, .. }
282283
| TerminatorKind::InlineAsm { unwind, .. }
283284
| TerminatorKind::Assert { unwind, .. }

compiler/rustc_codegen_ssa/src/mir/block.rs

+79-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::MemFlags;
1212
use rustc_ast as ast;
1313
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
1414
use rustc_hir::lang_items::LangItem;
15-
use rustc_middle::mir::{self, AssertKind, SwitchTargets, UnwindTerminateReason};
15+
use rustc_middle::mir::{self, AssertKind, SwitchTargets, UbCheckKind, UnwindTerminateReason};
1616
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement};
1717
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
1818
use rustc_middle::ty::{self, Instance, Ty};
@@ -737,6 +737,79 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
737737
}
738738
}
739739

740+
fn codegen_alignment_check(
741+
&mut self,
742+
helper: &TerminatorCodegenHelper<'tcx>,
743+
bx: &mut Bx,
744+
pointer: &mir::Operand<'tcx>,
745+
source_info: mir::SourceInfo,
746+
target: mir::BasicBlock,
747+
) -> MergingSucc {
748+
let span = source_info.span;
749+
let pointer = self.codegen_operand(bx, pointer);
750+
let pointee_ty = pointer.layout.ty.builtin_deref(true).unwrap();
751+
let pointee_layout = bx.layout_of(pointee_ty.ty);
752+
753+
let mk_usize = |v: u64| {
754+
let layout = bx.layout_of(bx.tcx().types.usize);
755+
let rustc_target::abi::Abi::Scalar(abi) = layout.abi else { unreachable!() };
756+
let v = rustc_middle::mir::interpret::Scalar::from_target_usize(v, &bx.tcx());
757+
bx.scalar_to_backend(v, abi, bx.cx().type_isize())
758+
};
759+
760+
let align = pointee_layout.align.abi.bytes();
761+
let mask = mk_usize(align - 1);
762+
let zero = mk_usize(0);
763+
let required = mk_usize(align);
764+
765+
let ptr_imm = match pointer.val {
766+
crate::mir::OperandValue::Immediate(imm) => imm,
767+
crate::mir::OperandValue::Pair(ptr, _) => ptr,
768+
_ => {
769+
unreachable!("{pointer:?}");
770+
}
771+
};
772+
let int_imm = bx.ptrtoint(ptr_imm, bx.cx().type_isize());
773+
774+
let masked = bx.and(int_imm, mask);
775+
776+
let is_zero = bx.icmp(
777+
crate::base::bin_op_to_icmp_predicate(mir::BinOp::Eq.to_hir_binop(), false),
778+
masked,
779+
zero,
780+
);
781+
782+
let lltarget = helper.llbb_with_cleanup(self, target);
783+
let panic_block = bx.append_sibling_block("panic");
784+
785+
bx.cond_br(is_zero, lltarget, panic_block);
786+
787+
bx.switch_to_block(panic_block);
788+
self.set_debug_loc(bx, source_info);
789+
790+
let location = self.get_caller_location(bx, source_info).immediate();
791+
792+
let found = int_imm;
793+
794+
let (lang_item, args) =
795+
(LangItem::PanicMisalignedPointerDereference, vec![required, found, location]);
796+
797+
let (fn_abi, llfn) = common::build_langcall(bx, Some(span), lang_item);
798+
let merging_succ = helper.do_call(
799+
self,
800+
bx,
801+
fn_abi,
802+
llfn,
803+
&args,
804+
None,
805+
mir::UnwindAction::Unreachable,
806+
&[],
807+
false,
808+
);
809+
assert_eq!(merging_succ, MergingSucc::False);
810+
MergingSucc::False
811+
}
812+
740813
fn codegen_call_terminator(
741814
&mut self,
742815
helper: TerminatorCodegenHelper<'tcx>,
@@ -1292,6 +1365,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
12921365
self.instance,
12931366
mergeable_succ(),
12941367
),
1368+
1369+
mir::TerminatorKind::UbCheck {
1370+
target,
1371+
kind: UbCheckKind::PointerAlignment { ref pointer },
1372+
} => self.codegen_alignment_check(&helper, bx, pointer, terminator.source_info, target),
12951373
}
12961374
}
12971375

compiler/rustc_const_eval/src/interpret/terminator.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
8585
self.pop_stack_frame(/* unwinding */ false)?
8686
}
8787

88-
Goto { target } => self.go_to_block(target),
88+
Goto { target } | UbCheck { target, .. } => self.go_to_block(target),
8989

9090
SwitchInt { ref discr, ref targets } => {
9191
let discr = self.read_immediate(&self.eval_operand(discr, None)?)?;

compiler/rustc_const_eval/src/transform/check_consts/check.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1058,7 +1058,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
10581058
| TerminatorKind::UnwindResume
10591059
| TerminatorKind::Return
10601060
| TerminatorKind::SwitchInt { .. }
1061-
| TerminatorKind::Unreachable => {}
1061+
| TerminatorKind::Unreachable
1062+
| TerminatorKind::UbCheck { .. } => {}
10621063
}
10631064
}
10641065
}

compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,8 @@ impl<'tcx> Visitor<'tcx> for CheckLiveDrops<'_, 'tcx> {
118118
| mir::TerminatorKind::Return
119119
| mir::TerminatorKind::SwitchInt { .. }
120120
| mir::TerminatorKind::Unreachable
121-
| mir::TerminatorKind::Yield { .. } => {}
121+
| mir::TerminatorKind::Yield { .. }
122+
| mir::TerminatorKind::UbCheck { .. } => {}
122123
}
123124
}
124125
}

compiler/rustc_const_eval/src/transform/validate.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
393393

394394
fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
395395
match &terminator.kind {
396-
TerminatorKind::Goto { target } => {
396+
TerminatorKind::Goto { target } | TerminatorKind::UbCheck { target, .. } => {
397397
self.check_edge(location, *target, EdgeKind::Normal);
398398
}
399399
TerminatorKind::SwitchInt { targets, discr: _ } => {
@@ -1299,7 +1299,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
12991299
| TerminatorKind::UnwindResume
13001300
| TerminatorKind::UnwindTerminate(_)
13011301
| TerminatorKind::Return
1302-
| TerminatorKind::Unreachable => {}
1302+
| TerminatorKind::Unreachable
1303+
| TerminatorKind::UbCheck { .. } => {}
13031304
}
13041305

13051306
self.super_terminator(terminator, location);

compiler/rustc_middle/src/mir/pretty.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -858,6 +858,9 @@ impl<'tcx> TerminatorKind<'tcx> {
858858
}
859859
write!(fmt, ", options({options:?}))")
860860
}
861+
UbCheck { target: _, kind: UbCheckKind::PointerAlignment { pointer } } => {
862+
write!(fmt, "pointer_alignment_check({pointer:?})")
863+
}
861864
}
862865
}
863866

@@ -866,7 +869,7 @@ impl<'tcx> TerminatorKind<'tcx> {
866869
use self::TerminatorKind::*;
867870
match *self {
868871
Return | UnwindResume | UnwindTerminate(_) | Unreachable | CoroutineDrop => vec![],
869-
Goto { .. } => vec!["".into()],
872+
Goto { .. } | UbCheck { .. } => vec!["".into()],
870873
SwitchInt { ref targets, .. } => targets
871874
.values
872875
.iter()

compiler/rustc_middle/src/mir/syntax.rs

+21-2
Original file line numberDiff line numberDiff line change
@@ -588,7 +588,9 @@ impl CallSource {
588588
#[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, TypeFoldable, TypeVisitable)]
589589
pub enum TerminatorKind<'tcx> {
590590
/// Block has one successor; we continue execution there.
591-
Goto { target: BasicBlock },
591+
Goto {
592+
target: BasicBlock,
593+
},
592594

593595
/// Switches based on the computed value.
594596
///
@@ -655,7 +657,12 @@ pub enum TerminatorKind<'tcx> {
655657
/// The `replace` flag indicates whether this terminator was created as part of an assignment.
656658
/// This should only be used for diagnostic purposes, and does not have any operational
657659
/// meaning.
658-
Drop { place: Place<'tcx>, target: BasicBlock, unwind: UnwindAction, replace: bool },
660+
Drop {
661+
place: Place<'tcx>,
662+
target: BasicBlock,
663+
unwind: UnwindAction,
664+
replace: bool,
665+
},
659666

660667
/// Roughly speaking, evaluates the `func` operand and the arguments, and starts execution of
661668
/// the referred to function. The operand types must match the argument types of the function.
@@ -798,6 +805,17 @@ pub enum TerminatorKind<'tcx> {
798805
/// if and only if InlineAsmOptions::MAY_UNWIND is set.
799806
unwind: UnwindAction,
800807
},
808+
809+
UbCheck {
810+
target: BasicBlock,
811+
kind: UbCheckKind<'tcx>,
812+
},
813+
}
814+
815+
#[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, TypeFoldable, TypeVisitable)]
816+
#[derive(Debug)]
817+
pub enum UbCheckKind<'tcx> {
818+
PointerAlignment { pointer: Operand<'tcx> },
801819
}
802820

803821
impl TerminatorKind<'_> {
@@ -819,6 +837,7 @@ impl TerminatorKind<'_> {
819837
TerminatorKind::FalseEdge { .. } => "FalseEdge",
820838
TerminatorKind::FalseUnwind { .. } => "FalseUnwind",
821839
TerminatorKind::InlineAsm { .. } => "InlineAsm",
840+
TerminatorKind::UbCheck { .. } => "UbCheck",
822841
}
823842
}
824843
}

compiler/rustc_middle/src/mir/terminator.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -348,9 +348,8 @@ impl<'tcx> TerminatorKind<'tcx> {
348348
| Assert { target: t, unwind: _, .. }
349349
| FalseUnwind { real_target: t, unwind: _ }
350350
| InlineAsm { destination: None, unwind: UnwindAction::Cleanup(t), .. }
351-
| InlineAsm { destination: Some(t), unwind: _, .. } => {
352-
Some(t).into_iter().chain((&[]).into_iter().copied())
353-
}
351+
| InlineAsm { destination: Some(t), unwind: _, .. }
352+
| UbCheck { target: t, .. } => Some(t).into_iter().chain((&[]).into_iter().copied()),
354353
UnwindResume
355354
| UnwindTerminate(_)
356355
| CoroutineDrop
@@ -390,9 +389,8 @@ impl<'tcx> TerminatorKind<'tcx> {
390389
| Assert { target: ref mut t, unwind: _, .. }
391390
| FalseUnwind { real_target: ref mut t, unwind: _ }
392391
| InlineAsm { destination: None, unwind: UnwindAction::Cleanup(ref mut t), .. }
393-
| InlineAsm { destination: Some(ref mut t), unwind: _, .. } => {
394-
Some(t).into_iter().chain(&mut [])
395-
}
392+
| InlineAsm { destination: Some(ref mut t), unwind: _, .. }
393+
| UbCheck { target: ref mut t, .. } => Some(t).into_iter().chain(&mut []),
396394
UnwindResume
397395
| UnwindTerminate(_)
398396
| CoroutineDrop
@@ -417,7 +415,8 @@ impl<'tcx> TerminatorKind<'tcx> {
417415
| TerminatorKind::CoroutineDrop
418416
| TerminatorKind::Yield { .. }
419417
| TerminatorKind::SwitchInt { .. }
420-
| TerminatorKind::FalseEdge { .. } => None,
418+
| TerminatorKind::FalseEdge { .. }
419+
| TerminatorKind::UbCheck { .. } => None,
421420
TerminatorKind::Call { ref unwind, .. }
422421
| TerminatorKind::Assert { ref unwind, .. }
423422
| TerminatorKind::Drop { ref unwind, .. }
@@ -436,7 +435,8 @@ impl<'tcx> TerminatorKind<'tcx> {
436435
| TerminatorKind::CoroutineDrop
437436
| TerminatorKind::Yield { .. }
438437
| TerminatorKind::SwitchInt { .. }
439-
| TerminatorKind::FalseEdge { .. } => None,
438+
| TerminatorKind::FalseEdge { .. }
439+
| TerminatorKind::UbCheck { .. } => None,
440440
TerminatorKind::Call { ref mut unwind, .. }
441441
| TerminatorKind::Assert { ref mut unwind, .. }
442442
| TerminatorKind::Drop { ref mut unwind, .. }
@@ -519,7 +519,7 @@ impl<'tcx> TerminatorKind<'tcx> {
519519
TerminatorEdges::None
520520
}
521521

522-
Goto { target } => TerminatorEdges::Single(target),
522+
Goto { target } | UbCheck { target, .. } => TerminatorEdges::Single(target),
523523

524524
Assert { target, unwind, expected: _, msg: _, cond: _ }
525525
| Drop { target, unwind, place: _, replace: _ }

compiler/rustc_middle/src/mir/visit.rs

+6
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,12 @@ macro_rules! make_mir_visitor {
599599
}
600600
}
601601
}
602+
TerminatorKind::UbCheck {
603+
kind: UbCheckKind::PointerAlignment { pointer },
604+
target: _,
605+
} => {
606+
self.visit_operand(pointer, location)
607+
}
602608
}
603609
}
604610

compiler/rustc_mir_build/src/build/scope.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1512,7 +1512,8 @@ impl<'tcx> DropTreeBuilder<'tcx> for Unwind {
15121512
| TerminatorKind::Unreachable
15131513
| TerminatorKind::Yield { .. }
15141514
| TerminatorKind::CoroutineDrop
1515-
| TerminatorKind::FalseEdge { .. } => {
1515+
| TerminatorKind::FalseEdge { .. }
1516+
| TerminatorKind::UbCheck { .. } => {
15161517
span_bug!(term.source_info.span, "cannot unwind from {:?}", term.kind)
15171518
}
15181519
}

compiler/rustc_mir_build/src/lints.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,8 @@ impl<'mir, 'tcx, C: TerminatorClassifier<'tcx>> TriColorVisitor<BasicBlocks<'tcx
214214
| TerminatorKind::FalseEdge { .. }
215215
| TerminatorKind::FalseUnwind { .. }
216216
| TerminatorKind::Goto { .. }
217-
| TerminatorKind::SwitchInt { .. } => ControlFlow::Continue(()),
217+
| TerminatorKind::SwitchInt { .. }
218+
| TerminatorKind::UbCheck { .. } => ControlFlow::Continue(()),
218219
}
219220
}
220221

compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,8 @@ where
143143
| TerminatorKind::Return
144144
| TerminatorKind::SwitchInt { .. }
145145
| TerminatorKind::Unreachable
146-
| TerminatorKind::Yield { .. } => {}
146+
| TerminatorKind::Yield { .. }
147+
| TerminatorKind::UbCheck { .. } => {}
147148
}
148149
}
149150
}

0 commit comments

Comments
 (0)