Skip to content

Commit 00e3be6

Browse files
[fixup] Correcltly handle empty unions and misc other fixes
1 parent 21854c1 commit 00e3be6

File tree

3 files changed

+76
-28
lines changed

3 files changed

+76
-28
lines changed

clang/include/clang/CodeGen/CGFunctionInfo.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,8 @@ class ABIArgInfo {
271271
// in the unpadded type.
272272
unsigned unpaddedIndex = 0;
273273
for (auto eltType : coerceToType->elements()) {
274-
if (isPaddingForCoerceAndExpand(eltType)) continue;
274+
if (isPaddingForCoerceAndExpand(eltType))
275+
continue;
275276
unpaddedIndex++;
276277
}
277278

clang/lib/CodeGen/Targets/AArch64.cpp

Lines changed: 35 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ class AArch64ABIInfo : public ABIInfo {
5252

5353
bool isIllegalVectorType(QualType Ty) const;
5454

55-
bool isPureScalableType(QualType Ty, unsigned &NV, unsigned &NP,
56-
SmallVectorImpl<llvm::Type *> &CoerceToSeq) const;
55+
bool passAsPureScalableType(QualType Ty, unsigned &NV, unsigned &NP,
56+
SmallVectorImpl<llvm::Type *> &CoerceToSeq) const;
5757

5858
void flattenType(llvm::Type *Ty,
5959
SmallVectorImpl<llvm::Type *> &Flattened) const;
@@ -432,7 +432,7 @@ ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty, bool IsVariadic,
432432
if (Kind == AArch64ABIKind::AAPCS && !IsVariadic) {
433433
unsigned NVec = 0, NPred = 0;
434434
SmallVector<llvm::Type *> UnpaddedCoerceToSeq;
435-
if (isPureScalableType(Ty, NVec, NPred, UnpaddedCoerceToSeq) &&
435+
if (passAsPureScalableType(Ty, NVec, NPred, UnpaddedCoerceToSeq) &&
436436
(NVec + NPred) > 0)
437437
return coerceAndExpandPureScalableAggregate(
438438
Ty, NVec, NPred, UnpaddedCoerceToSeq, NSRN, NPRN);
@@ -510,14 +510,14 @@ ABIArgInfo AArch64ABIInfo::classifyReturnType(QualType RetTy,
510510
// Homogeneous Floating-point Aggregates (HFAs) are returned directly.
511511
return ABIArgInfo::getDirect();
512512

513-
// In AAPCS return values of a Pure Scalable type are treated is a first named
514-
// argument and passed expanded in registers, or indirectly if there are not
515-
// enough registers.
513+
// In AAPCS return values of a Pure Scalable type are treated as a single
514+
// named argument and passed expanded in registers, or indirectly if there are
515+
// not enough registers.
516516
if (Kind == AArch64ABIKind::AAPCS) {
517517
unsigned NSRN = 0, NPRN = 0;
518518
unsigned NVec = 0, NPred = 0;
519519
SmallVector<llvm::Type *> UnpaddedCoerceToSeq;
520-
if (isPureScalableType(RetTy, NVec, NPred, UnpaddedCoerceToSeq) &&
520+
if (passAsPureScalableType(RetTy, NVec, NPred, UnpaddedCoerceToSeq) &&
521521
(NVec + NPred) > 0)
522522
return coerceAndExpandPureScalableAggregate(
523523
RetTy, NVec, NPred, UnpaddedCoerceToSeq, NSRN, NPRN);
@@ -638,13 +638,15 @@ bool AArch64ABIInfo::isZeroLengthBitfieldPermittedInHomogeneousAggregate()
638638
return true;
639639
}
640640

641-
// Check if a type is a Pure Scalable Type as defined by AAPCS64. Return the
642-
// number of data vectors and the number of predicate vectors in the types, into
643-
// `NVec` and `NPred`, respectively. Upon return `CoerceToSeq` contains an
644-
// expanded sequence of LLVM IR types, one element for each non-composite
645-
// member. For practical purposes, limit the length of `CoerceToSeq` to about
646-
// 12, the maximum size that could possibly fit in registers.
647-
bool AArch64ABIInfo::isPureScalableType(
641+
// Check if a type needs to be passed in registers as a Pure Scalable Type (as
642+
// defined by AAPCS64). Return the number of data vectors and the number of
643+
// predicate vectors in the type, into `NVec` and `NPred`, respectively. Upon
644+
// return `CoerceToSeq` contains an expanded sequence of LLVM IR types, one
645+
// element for each non-composite member. For practical purposes, limit the
646+
// length of `CoerceToSeq` to about 12 (the maximum that could possibly fit
647+
// in registers) and return false, the effect of which will be to pass the
648+
// argument under the rules for a large (> 128 bytes) composite.
649+
bool AArch64ABIInfo::passAsPureScalableType(
648650
QualType Ty, unsigned &NVec, unsigned &NPred,
649651
SmallVectorImpl<llvm::Type *> &CoerceToSeq) const {
650652
if (const ConstantArrayType *AT = getContext().getAsConstantArrayType(Ty)) {
@@ -654,10 +656,13 @@ bool AArch64ABIInfo::isPureScalableType(
654656

655657
unsigned NV = 0, NP = 0;
656658
SmallVector<llvm::Type *> EltCoerceToSeq;
657-
if (!isPureScalableType(AT->getElementType(), NV, NP, EltCoerceToSeq))
659+
if (!passAsPureScalableType(AT->getElementType(), NV, NP, EltCoerceToSeq))
658660
return false;
659661

660-
for (uint64_t I = 0; CoerceToSeq.size() < 12 && I < NElt; ++I)
662+
if (CoerceToSeq.size() + NElt * EltCoerceToSeq.size() > 12)
663+
return false;
664+
665+
for (uint64_t I = 0; I < NElt; ++I)
661666
llvm::copy(EltCoerceToSeq, std::back_inserter(CoerceToSeq));
662667

663668
NVec += NElt * NV;
@@ -676,22 +681,22 @@ bool AArch64ABIInfo::isPureScalableType(
676681
if (RD->isUnion())
677682
return false;
678683

679-
// If this is a C++ record, check the bases bases.
684+
// If this is a C++ record, check the bases.
680685
if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
681686
for (const auto &I : CXXRD->bases()) {
682687
if (isEmptyRecord(getContext(), I.getType(), true))
683688
continue;
684-
if (!isPureScalableType(I.getType(), NVec, NPred, CoerceToSeq))
689+
if (!passAsPureScalableType(I.getType(), NVec, NPred, CoerceToSeq))
685690
return false;
686691
}
687692
}
688693

689694
// Check members.
690695
for (const auto *FD : RD->fields()) {
691696
QualType FT = FD->getType();
692-
if (isEmptyRecord(getContext(), FT, true))
697+
if (isEmptyField(getContext(), FD, /* AllowArrays */ true))
693698
continue;
694-
if (!isPureScalableType(FT, NVec, NPred, CoerceToSeq))
699+
if (!passAsPureScalableType(FT, NVec, NPred, CoerceToSeq))
695700
return false;
696701
}
697702

@@ -704,15 +709,17 @@ bool AArch64ABIInfo::isPureScalableType(
704709

705710
if (VT->getVectorKind() == VectorKind::SveFixedLengthPredicate) {
706711
++NPred;
707-
if (CoerceToSeq.size() < 12)
708-
CoerceToSeq.push_back(convertFixedToScalableVectorType(VT));
712+
if (CoerceToSeq.size() + 1 > 12)
713+
return false;
714+
CoerceToSeq.push_back(convertFixedToScalableVectorType(VT));
709715
return true;
710716
}
711717

712718
if (VT->getVectorKind() == VectorKind::SveFixedLengthData) {
713719
++NVec;
714-
if (CoerceToSeq.size() < 12)
715-
CoerceToSeq.push_back(convertFixedToScalableVectorType(VT));
720+
if (CoerceToSeq.size() + 1 > 12)
721+
return false;
722+
CoerceToSeq.push_back(convertFixedToScalableVectorType(VT));
716723
return true;
717724
}
718725

@@ -741,8 +748,9 @@ bool AArch64ABIInfo::isPureScalableType(
741748
auto VTy = llvm::ScalableVectorType::get(CGT.ConvertType(Info.ElementType),
742749
Info.EC.getKnownMinValue());
743750

744-
if (CoerceToSeq.size() < 12)
745-
std::fill_n(std::back_inserter(CoerceToSeq), Info.NumVectors, VTy);
751+
if (CoerceToSeq.size() + Info.NumVectors > 12)
752+
return false;
753+
std::fill_n(std::back_inserter(CoerceToSeq), Info.NumVectors, VTy);
746754

747755
return true;
748756
}
@@ -784,7 +792,7 @@ RValue AArch64ABIInfo::EmitAAPCSVAArg(Address VAListAddr, QualType Ty,
784792
CodeGenFunction &CGF, AArch64ABIKind Kind,
785793
AggValueSlot Slot) const {
786794
// These numbers are not used for variadic arguments, hence it doesn't matter
787-
// they don't retain their values accross multiple calls to
795+
// they don't retain their values across multiple calls to
788796
// `classifyArgumentType` here.
789797
unsigned NSRN = 0, NPRN = 0;
790798
ABIArgInfo AI =
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// RUN: %clang_cc1 -O3 -triple aarch64 -target-feature +sve -mvscale-min=1 -mvscale-max=1 -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK-C
2+
// RUN: %clang_cc1 -x c++ -O3 -triple aarch64 -target-feature +sve -mvscale-min=1 -mvscale-max=1 -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK-CXX
3+
4+
typedef __SVFloat32_t fvec32 __attribute__((arm_sve_vector_bits(128)));
5+
6+
// PST containing an empty union: when compiled as C pass it in registers,
7+
// when compiled as C++ - in memory.
8+
typedef struct {
9+
fvec32 x[4];
10+
union {} u;
11+
} S0;
12+
13+
#ifdef __cplusplus
14+
extern "C"
15+
#endif
16+
void use0(S0);
17+
18+
void f0(S0 *p) {
19+
use0(*p);
20+
}
21+
// CHECK-C: declare void @use0(<vscale x 4 x float>, <vscale x 4 x float>, <vscale x 4 x float>, <vscale x 4 x float>)
22+
// CHECK-CXX: declare void @use0(ptr noundef)
23+
24+
#ifdef __cplusplus
25+
26+
// PST containing an empty union with `[[no_unique_address]]`` - pass in registers.
27+
typedef struct {
28+
fvec32 x[4];
29+
[[no_unique_address]]
30+
union {} u;
31+
} S1;
32+
33+
extern "C" void use1(S1);
34+
void f1(S1 *p) {
35+
use1(*p);
36+
}
37+
// CHECK-CXX: declare void @use1(<vscale x 4 x float>, <vscale x 4 x float>, <vscale x 4 x float>, <vscale x 4 x float>)
38+
39+
#endif // __cplusplus

0 commit comments

Comments
 (0)