Skip to content

Commit 030a471

Browse files
committed
[AArch64][Clang] Exclude address spaces from pointer-only coercion types.
As reported on #135064, the generic pointer coercion code in CoerceIntOrPtrToIntOrPtr cannot handle address space casts (it tries to bitcast the pointers). This bails out if an address space qualifier is found on the pointer.
1 parent c317eda commit 030a471

File tree

2 files changed

+181
-3
lines changed

2 files changed

+181
-3
lines changed

clang/lib/CodeGen/Targets/AArch64.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -507,7 +507,8 @@ ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty, bool IsVariadicFn,
507507
if (FDTy->isArrayType())
508508
FDTy = getContext().getBaseElementType(FDTy);
509509
return (FDTy->isPointerOrReferenceType() &&
510-
getContext().getTypeSize(FDTy) == 64) ||
510+
getContext().getTypeSize(FDTy) == 64 &&
511+
!FDTy->getPointeeType().hasAddressSpace()) ||
511512
Self(Self, FDTy);
512513
});
513514
};

clang/test/CodeGen/AArch64/struct-coerce-using-ptr.cpp

Lines changed: 179 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ struct Srp {
139139
// CHECK-A64-NEXT: [[S:%.*]] = alloca [[STRUCT_SRP:%.*]], align 8
140140
// CHECK-A64-NEXT: store [2 x ptr] [[S_COERCE]], ptr [[S]], align 8
141141
// CHECK-A64-NEXT: [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_SRP]], ptr [[S]], i32 0, i32 0
142-
// CHECK-A64-NEXT: [[TMP0:%.*]] = load ptr, ptr [[X]], align 8
142+
// CHECK-A64-NEXT: [[TMP0:%.*]] = load ptr, ptr [[X]], align 8, !nonnull [[META2:![0-9]+]], !align [[META3:![0-9]+]]
143143
// CHECK-A64-NEXT: store i32 1, ptr [[TMP0]], align 4
144144
// CHECK-A64-NEXT: ret void
145145
//
@@ -149,7 +149,7 @@ struct Srp {
149149
// CHECK-A64_32-NEXT: [[S:%.*]] = alloca [[STRUCT_SRP:%.*]], align 4
150150
// CHECK-A64_32-NEXT: store i64 [[S_COERCE]], ptr [[S]], align 4
151151
// CHECK-A64_32-NEXT: [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_SRP]], ptr [[S]], i32 0, i32 0
152-
// CHECK-A64_32-NEXT: [[TMP0:%.*]] = load ptr, ptr [[X]], align 4
152+
// CHECK-A64_32-NEXT: [[TMP0:%.*]] = load ptr, ptr [[X]], align 4, !nonnull [[META2:![0-9]+]], !align [[META3:![0-9]+]]
153153
// CHECK-A64_32-NEXT: store i32 1, ptr [[TMP0]], align 4
154154
// CHECK-A64_32-NEXT: ret void
155155
//
@@ -618,3 +618,180 @@ struct SpSempty {
618618
// CHECK-A64_32-NEXT: ret void
619619
//
620620
void TpSempty(SpSempty s) { *s.x = 1; }
621+
622+
623+
struct Spaddrspace {
624+
__attribute__((address_space(100))) int *x;
625+
};
626+
// CHECK-A64-LABEL: define dso_local void @_Z11Tpaddrspace11Spaddrspace(
627+
// CHECK-A64-SAME: i64 [[S_COERCE:%.*]]) #[[ATTR0]] {
628+
// CHECK-A64-NEXT: [[ENTRY:.*:]]
629+
// CHECK-A64-NEXT: [[S:%.*]] = alloca [[STRUCT_SPADDRSPACE:%.*]], align 8
630+
// CHECK-A64-NEXT: [[COERCE_DIVE:%.*]] = getelementptr inbounds nuw [[STRUCT_SPADDRSPACE]], ptr [[S]], i32 0, i32 0
631+
// CHECK-A64-NEXT: [[COERCE_VAL_IP:%.*]] = inttoptr i64 [[S_COERCE]] to ptr addrspace(100)
632+
// CHECK-A64-NEXT: store ptr addrspace(100) [[COERCE_VAL_IP]], ptr [[COERCE_DIVE]], align 8
633+
// CHECK-A64-NEXT: [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_SPADDRSPACE]], ptr [[S]], i32 0, i32 0
634+
// CHECK-A64-NEXT: [[TMP0:%.*]] = load ptr addrspace(100), ptr [[X]], align 8
635+
// CHECK-A64-NEXT: store i32 1, ptr addrspace(100) [[TMP0]], align 4
636+
// CHECK-A64-NEXT: ret void
637+
//
638+
// CHECK-A64_32-LABEL: define void @_Z11Tpaddrspace11Spaddrspace(
639+
// CHECK-A64_32-SAME: i64 [[S_COERCE:%.*]]) #[[ATTR0]] {
640+
// CHECK-A64_32-NEXT: [[ENTRY:.*:]]
641+
// CHECK-A64_32-NEXT: [[S:%.*]] = alloca [[STRUCT_SPADDRSPACE:%.*]], align 4
642+
// CHECK-A64_32-NEXT: [[COERCE_DIVE:%.*]] = getelementptr inbounds nuw [[STRUCT_SPADDRSPACE]], ptr [[S]], i32 0, i32 0
643+
// CHECK-A64_32-NEXT: [[COERCE_VAL_II:%.*]] = trunc i64 [[S_COERCE]] to i32
644+
// CHECK-A64_32-NEXT: store i32 [[COERCE_VAL_II]], ptr [[COERCE_DIVE]], align 4
645+
// CHECK-A64_32-NEXT: [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_SPADDRSPACE]], ptr [[S]], i32 0, i32 0
646+
// CHECK-A64_32-NEXT: [[TMP0:%.*]] = load ptr addrspace(100), ptr [[X]], align 4
647+
// CHECK-A64_32-NEXT: store i32 1, ptr addrspace(100) [[TMP0]], align 4
648+
// CHECK-A64_32-NEXT: ret void
649+
//
650+
void Tpaddrspace(Spaddrspace s) { *s.x = 1; }
651+
// CHECK-A64-LABEL: define dso_local void @_Z11Cpaddrspacev(
652+
// CHECK-A64-SAME: ) #[[ATTR0]] {
653+
// CHECK-A64-NEXT: [[ENTRY:.*:]]
654+
// CHECK-A64-NEXT: [[S:%.*]] = alloca [[STRUCT_SPADDRSPACE:%.*]], align 8
655+
// CHECK-A64-NEXT: [[AGG_TMP:%.*]] = alloca [[STRUCT_SPADDRSPACE]], align 8
656+
// CHECK-A64-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TMP]], ptr align 8 [[S]], i64 8, i1 false)
657+
// CHECK-A64-NEXT: [[COERCE_DIVE:%.*]] = getelementptr inbounds nuw [[STRUCT_SPADDRSPACE]], ptr [[AGG_TMP]], i32 0, i32 0
658+
// CHECK-A64-NEXT: [[TMP0:%.*]] = load ptr addrspace(100), ptr [[COERCE_DIVE]], align 8
659+
// CHECK-A64-NEXT: [[COERCE_VAL_PI:%.*]] = ptrtoint ptr addrspace(100) [[TMP0]] to i64
660+
// CHECK-A64-NEXT: call void @_Z11Tpaddrspace11Spaddrspace(i64 [[COERCE_VAL_PI]])
661+
// CHECK-A64-NEXT: ret void
662+
//
663+
// CHECK-A64_32-LABEL: define void @_Z11Cpaddrspacev(
664+
// CHECK-A64_32-SAME: ) #[[ATTR0]] {
665+
// CHECK-A64_32-NEXT: [[ENTRY:.*:]]
666+
// CHECK-A64_32-NEXT: [[S:%.*]] = alloca [[STRUCT_SPADDRSPACE:%.*]], align 4
667+
// CHECK-A64_32-NEXT: [[AGG_TMP:%.*]] = alloca [[STRUCT_SPADDRSPACE]], align 4
668+
// CHECK-A64_32-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[AGG_TMP]], ptr align 4 [[S]], i32 4, i1 false)
669+
// CHECK-A64_32-NEXT: [[COERCE_DIVE:%.*]] = getelementptr inbounds nuw [[STRUCT_SPADDRSPACE]], ptr [[AGG_TMP]], i32 0, i32 0
670+
// CHECK-A64_32-NEXT: [[TMP0:%.*]] = load ptr addrspace(100), ptr [[COERCE_DIVE]], align 4
671+
// CHECK-A64_32-NEXT: [[COERCE_VAL_PI:%.*]] = ptrtoint ptr addrspace(100) [[TMP0]] to i32
672+
// CHECK-A64_32-NEXT: [[COERCE_VAL_II:%.*]] = zext i32 [[COERCE_VAL_PI]] to i64
673+
// CHECK-A64_32-NEXT: call void @_Z11Tpaddrspace11Spaddrspace(i64 [[COERCE_VAL_II]])
674+
// CHECK-A64_32-NEXT: ret void
675+
//
676+
void Cpaddrspace() { Spaddrspace s; Tpaddrspace(s); }
677+
678+
struct Sp2addrspace {
679+
__attribute__((address_space(100))) int *x[2];
680+
};
681+
// CHECK-A64-LABEL: define dso_local void @_Z12Tp2addrspace12Sp2addrspace(
682+
// CHECK-A64-SAME: [2 x i64] [[S_COERCE:%.*]]) #[[ATTR0]] {
683+
// CHECK-A64-NEXT: [[ENTRY:.*:]]
684+
// CHECK-A64-NEXT: [[S:%.*]] = alloca [[STRUCT_SP2ADDRSPACE:%.*]], align 8
685+
// CHECK-A64-NEXT: [[COERCE_DIVE:%.*]] = getelementptr inbounds nuw [[STRUCT_SP2ADDRSPACE]], ptr [[S]], i32 0, i32 0
686+
// CHECK-A64-NEXT: store [2 x i64] [[S_COERCE]], ptr [[COERCE_DIVE]], align 8
687+
// CHECK-A64-NEXT: [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_SP2ADDRSPACE]], ptr [[S]], i32 0, i32 0
688+
// CHECK-A64-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x ptr addrspace(100)], ptr [[X]], i64 0, i64 0
689+
// CHECK-A64-NEXT: [[TMP0:%.*]] = load ptr addrspace(100), ptr [[ARRAYIDX]], align 8
690+
// CHECK-A64-NEXT: store i32 1, ptr addrspace(100) [[TMP0]], align 4
691+
// CHECK-A64-NEXT: ret void
692+
//
693+
// CHECK-A64_32-LABEL: define void @_Z12Tp2addrspace12Sp2addrspace(
694+
// CHECK-A64_32-SAME: i64 [[S_COERCE:%.*]]) #[[ATTR0]] {
695+
// CHECK-A64_32-NEXT: [[ENTRY:.*:]]
696+
// CHECK-A64_32-NEXT: [[S:%.*]] = alloca [[STRUCT_SP2ADDRSPACE:%.*]], align 4
697+
// CHECK-A64_32-NEXT: [[COERCE_DIVE:%.*]] = getelementptr inbounds nuw [[STRUCT_SP2ADDRSPACE]], ptr [[S]], i32 0, i32 0
698+
// CHECK-A64_32-NEXT: store i64 [[S_COERCE]], ptr [[COERCE_DIVE]], align 4
699+
// CHECK-A64_32-NEXT: [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_SP2ADDRSPACE]], ptr [[S]], i32 0, i32 0
700+
// CHECK-A64_32-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x ptr addrspace(100)], ptr [[X]], i32 0, i32 0
701+
// CHECK-A64_32-NEXT: [[TMP0:%.*]] = load ptr addrspace(100), ptr [[ARRAYIDX]], align 4
702+
// CHECK-A64_32-NEXT: store i32 1, ptr addrspace(100) [[TMP0]], align 4
703+
// CHECK-A64_32-NEXT: ret void
704+
//
705+
void Tp2addrspace(Sp2addrspace s) { *s.x[0] = 1; }
706+
// CHECK-A64-LABEL: define dso_local void @_Z12Cp2addrspacev(
707+
// CHECK-A64-SAME: ) #[[ATTR0]] {
708+
// CHECK-A64-NEXT: [[ENTRY:.*:]]
709+
// CHECK-A64-NEXT: [[S:%.*]] = alloca [[STRUCT_SP2ADDRSPACE:%.*]], align 8
710+
// CHECK-A64-NEXT: [[AGG_TMP:%.*]] = alloca [[STRUCT_SP2ADDRSPACE]], align 8
711+
// CHECK-A64-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TMP]], ptr align 8 [[S]], i64 16, i1 false)
712+
// CHECK-A64-NEXT: [[COERCE_DIVE:%.*]] = getelementptr inbounds nuw [[STRUCT_SP2ADDRSPACE]], ptr [[AGG_TMP]], i32 0, i32 0
713+
// CHECK-A64-NEXT: [[TMP0:%.*]] = load [2 x i64], ptr [[COERCE_DIVE]], align 8
714+
// CHECK-A64-NEXT: call void @_Z12Tp2addrspace12Sp2addrspace([2 x i64] [[TMP0]])
715+
// CHECK-A64-NEXT: ret void
716+
//
717+
// CHECK-A64_32-LABEL: define void @_Z12Cp2addrspacev(
718+
// CHECK-A64_32-SAME: ) #[[ATTR0]] {
719+
// CHECK-A64_32-NEXT: [[ENTRY:.*:]]
720+
// CHECK-A64_32-NEXT: [[S:%.*]] = alloca [[STRUCT_SP2ADDRSPACE:%.*]], align 4
721+
// CHECK-A64_32-NEXT: [[AGG_TMP:%.*]] = alloca [[STRUCT_SP2ADDRSPACE]], align 4
722+
// CHECK-A64_32-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[AGG_TMP]], ptr align 4 [[S]], i32 8, i1 false)
723+
// CHECK-A64_32-NEXT: [[COERCE_DIVE:%.*]] = getelementptr inbounds nuw [[STRUCT_SP2ADDRSPACE]], ptr [[AGG_TMP]], i32 0, i32 0
724+
// CHECK-A64_32-NEXT: [[TMP0:%.*]] = load i64, ptr [[COERCE_DIVE]], align 4
725+
// CHECK-A64_32-NEXT: call void @_Z12Tp2addrspace12Sp2addrspace(i64 [[TMP0]])
726+
// CHECK-A64_32-NEXT: ret void
727+
//
728+
void Cp2addrspace() { Sp2addrspace s; Tp2addrspace(s); }
729+
730+
struct Sraddrspace {
731+
__attribute__((address_space(100))) int &x;
732+
};
733+
// CHECK-A64-LABEL: define dso_local void @_Z11Traddrspace11Sraddrspace(
734+
// CHECK-A64-SAME: i64 [[S_COERCE:%.*]]) #[[ATTR0]] {
735+
// CHECK-A64-NEXT: [[ENTRY:.*:]]
736+
// CHECK-A64-NEXT: [[S:%.*]] = alloca [[STRUCT_SRADDRSPACE:%.*]], align 8
737+
// CHECK-A64-NEXT: [[COERCE_DIVE:%.*]] = getelementptr inbounds nuw [[STRUCT_SRADDRSPACE]], ptr [[S]], i32 0, i32 0
738+
// CHECK-A64-NEXT: [[COERCE_VAL_IP:%.*]] = inttoptr i64 [[S_COERCE]] to ptr addrspace(100)
739+
// CHECK-A64-NEXT: store ptr addrspace(100) [[COERCE_VAL_IP]], ptr [[COERCE_DIVE]], align 8
740+
// CHECK-A64-NEXT: [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_SRADDRSPACE]], ptr [[S]], i32 0, i32 0
741+
// CHECK-A64-NEXT: [[TMP0:%.*]] = load ptr addrspace(100), ptr [[X]], align 8, !align [[META3]]
742+
// CHECK-A64-NEXT: store i32 1, ptr addrspace(100) [[TMP0]], align 4
743+
// CHECK-A64-NEXT: ret void
744+
//
745+
// CHECK-A64_32-LABEL: define void @_Z11Traddrspace11Sraddrspace(
746+
// CHECK-A64_32-SAME: i64 [[S_COERCE:%.*]]) #[[ATTR0]] {
747+
// CHECK-A64_32-NEXT: [[ENTRY:.*:]]
748+
// CHECK-A64_32-NEXT: [[S:%.*]] = alloca [[STRUCT_SRADDRSPACE:%.*]], align 4
749+
// CHECK-A64_32-NEXT: [[COERCE_DIVE:%.*]] = getelementptr inbounds nuw [[STRUCT_SRADDRSPACE]], ptr [[S]], i32 0, i32 0
750+
// CHECK-A64_32-NEXT: [[COERCE_VAL_II:%.*]] = trunc i64 [[S_COERCE]] to i32
751+
// CHECK-A64_32-NEXT: store i32 [[COERCE_VAL_II]], ptr [[COERCE_DIVE]], align 4
752+
// CHECK-A64_32-NEXT: [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_SRADDRSPACE]], ptr [[S]], i32 0, i32 0
753+
// CHECK-A64_32-NEXT: [[TMP0:%.*]] = load ptr addrspace(100), ptr [[X]], align 4, !align [[META3]]
754+
// CHECK-A64_32-NEXT: store i32 1, ptr addrspace(100) [[TMP0]], align 4
755+
// CHECK-A64_32-NEXT: ret void
756+
//
757+
void Traddrspace(Sraddrspace s) { s.x = 1; }
758+
// CHECK-A64-LABEL: define dso_local void @_Z11Craddrspace11Sraddrspace(
759+
// CHECK-A64-SAME: i64 [[S_COERCE:%.*]]) #[[ATTR0]] {
760+
// CHECK-A64-NEXT: [[ENTRY:.*:]]
761+
// CHECK-A64-NEXT: [[S:%.*]] = alloca [[STRUCT_SRADDRSPACE:%.*]], align 8
762+
// CHECK-A64-NEXT: [[AGG_TMP:%.*]] = alloca [[STRUCT_SRADDRSPACE]], align 8
763+
// CHECK-A64-NEXT: [[COERCE_DIVE:%.*]] = getelementptr inbounds nuw [[STRUCT_SRADDRSPACE]], ptr [[S]], i32 0, i32 0
764+
// CHECK-A64-NEXT: [[COERCE_VAL_IP:%.*]] = inttoptr i64 [[S_COERCE]] to ptr addrspace(100)
765+
// CHECK-A64-NEXT: store ptr addrspace(100) [[COERCE_VAL_IP]], ptr [[COERCE_DIVE]], align 8
766+
// CHECK-A64-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TMP]], ptr align 8 [[S]], i64 8, i1 false)
767+
// CHECK-A64-NEXT: [[COERCE_DIVE1:%.*]] = getelementptr inbounds nuw [[STRUCT_SRADDRSPACE]], ptr [[AGG_TMP]], i32 0, i32 0
768+
// CHECK-A64-NEXT: [[TMP0:%.*]] = load ptr addrspace(100), ptr [[COERCE_DIVE1]], align 8
769+
// CHECK-A64-NEXT: [[COERCE_VAL_PI:%.*]] = ptrtoint ptr addrspace(100) [[TMP0]] to i64
770+
// CHECK-A64-NEXT: call void @_Z11Traddrspace11Sraddrspace(i64 [[COERCE_VAL_PI]])
771+
// CHECK-A64-NEXT: ret void
772+
//
773+
// CHECK-A64_32-LABEL: define void @_Z11Craddrspace11Sraddrspace(
774+
// CHECK-A64_32-SAME: i64 [[S_COERCE:%.*]]) #[[ATTR0]] {
775+
// CHECK-A64_32-NEXT: [[ENTRY:.*:]]
776+
// CHECK-A64_32-NEXT: [[S:%.*]] = alloca [[STRUCT_SRADDRSPACE:%.*]], align 4
777+
// CHECK-A64_32-NEXT: [[AGG_TMP:%.*]] = alloca [[STRUCT_SRADDRSPACE]], align 4
778+
// CHECK-A64_32-NEXT: [[COERCE_DIVE:%.*]] = getelementptr inbounds nuw [[STRUCT_SRADDRSPACE]], ptr [[S]], i32 0, i32 0
779+
// CHECK-A64_32-NEXT: [[COERCE_VAL_II:%.*]] = trunc i64 [[S_COERCE]] to i32
780+
// CHECK-A64_32-NEXT: store i32 [[COERCE_VAL_II]], ptr [[COERCE_DIVE]], align 4
781+
// CHECK-A64_32-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[AGG_TMP]], ptr align 4 [[S]], i32 4, i1 false)
782+
// CHECK-A64_32-NEXT: [[COERCE_DIVE1:%.*]] = getelementptr inbounds nuw [[STRUCT_SRADDRSPACE]], ptr [[AGG_TMP]], i32 0, i32 0
783+
// CHECK-A64_32-NEXT: [[TMP0:%.*]] = load ptr addrspace(100), ptr [[COERCE_DIVE1]], align 4
784+
// CHECK-A64_32-NEXT: [[COERCE_VAL_PI:%.*]] = ptrtoint ptr addrspace(100) [[TMP0]] to i32
785+
// CHECK-A64_32-NEXT: [[COERCE_VAL_II2:%.*]] = zext i32 [[COERCE_VAL_PI]] to i64
786+
// CHECK-A64_32-NEXT: call void @_Z11Traddrspace11Sraddrspace(i64 [[COERCE_VAL_II2]])
787+
// CHECK-A64_32-NEXT: ret void
788+
//
789+
void Craddrspace(Sraddrspace s) { Traddrspace(s); }
790+
791+
//.
792+
// CHECK-A64: [[META2]] = !{}
793+
// CHECK-A64: [[META3]] = !{i64 4}
794+
//.
795+
// CHECK-A64_32: [[META2]] = !{}
796+
// CHECK-A64_32: [[META3]] = !{i64 4}
797+
//.

0 commit comments

Comments
 (0)