@@ -7418,18 +7418,28 @@ class SystemZABIInfo : public ABIInfo {
7418
7418
};
7419
7419
7420
7420
class SystemZTargetCodeGenInfo : public TargetCodeGenInfo {
7421
+ ASTContext &Ctx;
7422
+
7423
+ const SystemZABIInfo &getABIInfo () const {
7424
+ return static_cast <const SystemZABIInfo&>(TargetCodeGenInfo::getABIInfo ());
7425
+ }
7426
+
7421
7427
// These are used for speeding up the search for a visible vector ABI.
7422
7428
mutable bool HasVisibleVecABIFlag = false ;
7423
7429
mutable std::set<const Type *> SeenTypes;
7424
7430
7425
- // Returns true (the first time) if Ty is or found to make use of a vector
7426
- // type (e.g. as a function argument).
7427
- bool isVectorTypeBased (const Type *Ty) const ;
7431
+ // Returns true (the first time) if Ty is, or is found to include, a vector
7432
+ // type that exposes the vector ABI. This is any vector >=16 bytes which
7433
+ // with vector support are aligned to only 8 bytes. When IsParam is true,
7434
+ // the type belongs to a value as passed between functions. If it is a
7435
+ // vector <=16 bytes it will be passed in a vector register (if supported).
7436
+ bool isVectorTypeBased (const Type *Ty, bool IsParam) const ;
7428
7437
7429
7438
public:
7430
7439
SystemZTargetCodeGenInfo (CodeGenTypes &CGT, bool HasVector, bool SoftFloatABI)
7431
7440
: TargetCodeGenInfo(
7432
- std::make_unique<SystemZABIInfo>(CGT, HasVector, SoftFloatABI)) {
7441
+ std::make_unique<SystemZABIInfo>(CGT, HasVector, SoftFloatABI)),
7442
+ Ctx (CGT.getContext()) {
7433
7443
SwiftInfo =
7434
7444
std::make_unique<SwiftABIInfo>(CGT, /* SwiftErrorInRegister=*/ false );
7435
7445
}
@@ -7439,9 +7449,9 @@ class SystemZTargetCodeGenInfo : public TargetCodeGenInfo {
7439
7449
// indicating a visible vector ABI is added. Eventually this will result in
7440
7450
// a GNU attribute indicating the vector ABI of the module. Ty is the type
7441
7451
// of a variable or function parameter that is globally visible.
7442
- void handleExternallyVisibleObjABI (const Type *Ty,
7443
- CodeGen::CodeGenModule &M ) const {
7444
- if (!HasVisibleVecABIFlag && isVectorTypeBased (Ty)) {
7452
+ void handleExternallyVisibleObjABI (const Type *Ty, CodeGen::CodeGenModule &M,
7453
+ bool IsParam ) const {
7454
+ if (!HasVisibleVecABIFlag && isVectorTypeBased (Ty, IsParam )) {
7445
7455
M.getModule ().addModuleFlag (llvm::Module::Warning,
7446
7456
" s390x-visible-vector-ABI" , 1 );
7447
7457
HasVisibleVecABIFlag = true ;
@@ -7457,11 +7467,13 @@ class SystemZTargetCodeGenInfo : public TargetCodeGenInfo {
7457
7467
// variable or function.
7458
7468
if (const auto *VD = dyn_cast<VarDecl>(D)) {
7459
7469
if (VD->isExternallyVisible ())
7460
- handleExternallyVisibleObjABI (VD->getType ().getTypePtr (), M);
7470
+ handleExternallyVisibleObjABI (VD->getType ().getTypePtr (), M,
7471
+ /* IsParam*/ false );
7461
7472
}
7462
7473
else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
7463
7474
if (FD->isExternallyVisible ())
7464
- handleExternallyVisibleObjABI (FD->getType ().getTypePtr (), M);
7475
+ handleExternallyVisibleObjABI (FD->getType ().getTypePtr (), M,
7476
+ /* IsParam*/ false );
7465
7477
}
7466
7478
}
7467
7479
@@ -7571,17 +7583,18 @@ QualType SystemZABIInfo::GetSingleElementType(QualType Ty) const {
7571
7583
7572
7584
// If this is a C++ record, check the bases first.
7573
7585
if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD))
7574
- for (const auto &I : CXXRD->bases ()) {
7575
- QualType Base = I.getType ();
7586
+ if (CXXRD->hasDefinition ())
7587
+ for (const auto &I : CXXRD->bases ()) {
7588
+ QualType Base = I.getType ();
7576
7589
7577
- // Empty bases don't affect things either way.
7578
- if (isEmptyRecord (getContext (), Base, true ))
7579
- continue ;
7590
+ // Empty bases don't affect things either way.
7591
+ if (isEmptyRecord (getContext (), Base, true ))
7592
+ continue ;
7580
7593
7581
- if (!Found.isNull ())
7582
- return Ty;
7583
- Found = GetSingleElementType (Base);
7584
- }
7594
+ if (!Found.isNull ())
7595
+ return Ty;
7596
+ Found = GetSingleElementType (Base);
7597
+ }
7585
7598
7586
7599
// Check the fields.
7587
7600
for (const auto *FD : RD->fields ()) {
@@ -7635,7 +7648,8 @@ Address SystemZABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
7635
7648
bool IsVector = false ;
7636
7649
CharUnits UnpaddedSize;
7637
7650
CharUnits DirectAlign;
7638
- SZCGI.handleExternallyVisibleObjABI (Ty.getTypePtr (), CGT.getCGM ());
7651
+ SZCGI.handleExternallyVisibleObjABI (Ty.getTypePtr (), CGT.getCGM (),
7652
+ /* IsParam*/ true );
7639
7653
if (IsIndirect) {
7640
7654
DirectTy = llvm::PointerType::getUnqual (DirectTy);
7641
7655
UnpaddedSize = DirectAlign = CharUnits::fromQuantity (8 );
@@ -7843,35 +7857,57 @@ void SystemZABIInfo::computeInfo(CGFunctionInfo &FI) const {
7843
7857
// Check if a vararg vector argument is passed, in which case the
7844
7858
// vector ABI becomes visible as the va_list could be passed on to
7845
7859
// other functions.
7846
- SZCGI.handleExternallyVisibleObjABI (I.type .getTypePtr (), CGT.getCGM ());
7860
+ SZCGI.handleExternallyVisibleObjABI (I.type .getTypePtr (), CGT.getCGM (),
7861
+ /* IsParam*/ true );
7847
7862
}
7848
7863
}
7849
7864
7850
- bool SystemZTargetCodeGenInfo::isVectorTypeBased (const Type *Ty) const {
7851
- while (Ty->isPointerType () || Ty->isArrayType ())
7852
- Ty = Ty->getPointeeOrArrayElementType ();
7865
+ bool SystemZTargetCodeGenInfo::isVectorTypeBased (const Type *Ty,
7866
+ bool IsParam) const {
7853
7867
if (!SeenTypes.insert (Ty).second )
7854
7868
return false ;
7855
- if (Ty->isVectorType ())
7856
- return true ;
7869
+
7870
+ if (IsParam) {
7871
+ // A narrow (<16 bytes) vector will as a parameter also expose the ABI as
7872
+ // it will be passed in a vector register. A wide (>16 bytes) vector will
7873
+ // be passed via "hidden" pointer where any extra alignment is not
7874
+ // required (per GCC).
7875
+ const Type *SingleEltTy =
7876
+ getABIInfo ().GetSingleElementType (QualType (Ty, 0 )).getTypePtr ();
7877
+ bool SingleVecEltStruct = SingleEltTy != Ty && SingleEltTy->isVectorType () &&
7878
+ Ctx.getTypeSize (SingleEltTy) == Ctx.getTypeSize (Ty);
7879
+ if (Ty->isVectorType () || SingleVecEltStruct)
7880
+ return Ctx.getTypeSize (Ty) / 8 <= 16 ;
7881
+ }
7882
+
7883
+ // Assume pointers are dereferenced.
7884
+ while (Ty->isPointerType () || Ty->isArrayType ())
7885
+ Ty = Ty->getPointeeOrArrayElementType ();
7886
+
7887
+ // Vectors >= 16 bytes expose the ABI through alignment requirements.
7888
+ if (Ty->isVectorType () && Ctx.getTypeSize (Ty) / 8 >= 16 )
7889
+ return true ;
7890
+
7857
7891
if (const auto *RecordTy = Ty->getAs <RecordType>()) {
7858
7892
const RecordDecl *RD = RecordTy->getDecl ();
7859
7893
if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD))
7860
7894
if (CXXRD->hasDefinition ())
7861
7895
for (const auto &I : CXXRD->bases ())
7862
- if (isVectorTypeBased (I.getType ().getTypePtr ()))
7896
+ if (isVectorTypeBased (I.getType ().getTypePtr (), /* IsParam */ false ))
7863
7897
return true ;
7864
7898
for (const auto *FD : RD->fields ())
7865
- if (isVectorTypeBased (FD->getType ().getTypePtr ()))
7899
+ if (isVectorTypeBased (FD->getType ().getTypePtr (), /* IsParam */ false ))
7866
7900
return true ;
7867
7901
}
7902
+
7868
7903
if (const auto *FT = Ty->getAs <FunctionType>())
7869
- if (isVectorTypeBased (FT->getReturnType ().getTypePtr ()))
7904
+ if (isVectorTypeBased (FT->getReturnType ().getTypePtr (), /* IsParam */ true ))
7870
7905
return true ;
7871
7906
if (const FunctionProtoType *Proto = Ty->getAs <FunctionProtoType>())
7872
7907
for (auto ParamType : Proto->getParamTypes ())
7873
- if (isVectorTypeBased (ParamType.getTypePtr ()))
7908
+ if (isVectorTypeBased (ParamType.getTypePtr (), /* IsParam */ true ))
7874
7909
return true ;
7910
+
7875
7911
return false ;
7876
7912
}
7877
7913
0 commit comments