@@ -12,7 +12,7 @@ use crate::MemFlags;
12
12
use rustc_ast as ast;
13
13
use rustc_ast:: { InlineAsmOptions , InlineAsmTemplatePiece } ;
14
14
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 } ;
16
16
use rustc_middle:: ty:: layout:: { HasTyCtxt , LayoutOf , ValidityRequirement } ;
17
17
use rustc_middle:: ty:: print:: { with_no_trimmed_paths, with_no_visible_paths} ;
18
18
use rustc_middle:: ty:: { self , Instance , Ty } ;
@@ -737,6 +737,79 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
737
737
}
738
738
}
739
739
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
+
740
813
fn codegen_call_terminator (
741
814
& mut self ,
742
815
helper : TerminatorCodegenHelper < ' tcx > ,
@@ -1292,6 +1365,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
1292
1365
self . instance ,
1293
1366
mergeable_succ ( ) ,
1294
1367
) ,
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) ,
1295
1373
}
1296
1374
}
1297
1375
0 commit comments