@@ -12,7 +12,7 @@ use crate::MemFlags;
1212use rustc_ast as ast;
1313use rustc_ast:: { InlineAsmOptions , InlineAsmTemplatePiece } ;
1414use rustc_hir:: lang_items:: LangItem ;
15- use rustc_middle:: mir:: { self , AssertKind , SwitchTargets , UnwindTerminateReason } ;
15+ use rustc_middle:: mir:: { self , AssertKind , SwitchTargets , UbCheckKind , UnwindTerminateReason } ;
1616use rustc_middle:: ty:: layout:: { HasTyCtxt , LayoutOf , ValidityRequirement } ;
1717use rustc_middle:: ty:: print:: { with_no_trimmed_paths, with_no_visible_paths} ;
1818use 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
0 commit comments