diff options
Diffstat (limited to 'clang/lib/CodeGen/TargetInfo.cpp')
| -rw-r--r-- | clang/lib/CodeGen/TargetInfo.cpp | 94 |
1 files changed, 65 insertions, 29 deletions
diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index be1dbe8480c6..a9119abad81d 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -7418,18 +7418,28 @@ public: }; class SystemZTargetCodeGenInfo : public TargetCodeGenInfo { + ASTContext &Ctx; + + const SystemZABIInfo &getABIInfo() const { + return static_cast<const SystemZABIInfo&>(TargetCodeGenInfo::getABIInfo()); + } + // These are used for speeding up the search for a visible vector ABI. mutable bool HasVisibleVecABIFlag = false; mutable std::set<const Type *> SeenTypes; - // Returns true (the first time) if Ty is or found to make use of a vector - // type (e.g. as a function argument). - bool isVectorTypeBased(const Type *Ty) const; + // Returns true (the first time) if Ty is, or is found to include, a vector + // type that exposes the vector ABI. This is any vector >=16 bytes which + // with vector support are aligned to only 8 bytes. When IsParam is true, + // the type belongs to a value as passed between functions. If it is a + // vector <=16 bytes it will be passed in a vector register (if supported). + bool isVectorTypeBased(const Type *Ty, bool IsParam) const; public: SystemZTargetCodeGenInfo(CodeGenTypes &CGT, bool HasVector, bool SoftFloatABI) : TargetCodeGenInfo( - std::make_unique<SystemZABIInfo>(CGT, HasVector, SoftFloatABI)) { + std::make_unique<SystemZABIInfo>(CGT, HasVector, SoftFloatABI)), + Ctx(CGT.getContext()) { SwiftInfo = std::make_unique<SwiftABIInfo>(CGT, /*SwiftErrorInRegister=*/false); } @@ -7439,9 +7449,9 @@ public: // indicating a visible vector ABI is added. Eventually this will result in // a GNU attribute indicating the vector ABI of the module. Ty is the type // of a variable or function parameter that is globally visible. - void handleExternallyVisibleObjABI(const Type *Ty, - CodeGen::CodeGenModule &M) const { - if (!HasVisibleVecABIFlag && isVectorTypeBased(Ty)) { + void handleExternallyVisibleObjABI(const Type *Ty, CodeGen::CodeGenModule &M, + bool IsParam) const { + if (!HasVisibleVecABIFlag && isVectorTypeBased(Ty, IsParam)) { M.getModule().addModuleFlag(llvm::Module::Warning, "s390x-visible-vector-ABI", 1); HasVisibleVecABIFlag = true; @@ -7457,11 +7467,13 @@ public: // variable or function. if (const auto *VD = dyn_cast<VarDecl>(D)) { if (VD->isExternallyVisible()) - handleExternallyVisibleObjABI(VD->getType().getTypePtr(), M); + handleExternallyVisibleObjABI(VD->getType().getTypePtr(), M, + /*IsParam*/false); } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { if (FD->isExternallyVisible()) - handleExternallyVisibleObjABI(FD->getType().getTypePtr(), M); + handleExternallyVisibleObjABI(FD->getType().getTypePtr(), M, + /*IsParam*/false); } } @@ -7571,17 +7583,18 @@ QualType SystemZABIInfo::GetSingleElementType(QualType Ty) const { // If this is a C++ record, check the bases first. if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) - for (const auto &I : CXXRD->bases()) { - QualType Base = I.getType(); + if (CXXRD->hasDefinition()) + for (const auto &I : CXXRD->bases()) { + QualType Base = I.getType(); - // Empty bases don't affect things either way. - if (isEmptyRecord(getContext(), Base, true)) - continue; + // Empty bases don't affect things either way. + if (isEmptyRecord(getContext(), Base, true)) + continue; - if (!Found.isNull()) - return Ty; - Found = GetSingleElementType(Base); - } + if (!Found.isNull()) + return Ty; + Found = GetSingleElementType(Base); + } // Check the fields. for (const auto *FD : RD->fields()) { @@ -7635,7 +7648,8 @@ Address SystemZABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, bool IsVector = false; CharUnits UnpaddedSize; CharUnits DirectAlign; - SZCGI.handleExternallyVisibleObjABI(Ty.getTypePtr(), CGT.getCGM()); + SZCGI.handleExternallyVisibleObjABI(Ty.getTypePtr(), CGT.getCGM(), + /*IsParam*/true); if (IsIndirect) { DirectTy = llvm::PointerType::getUnqual(DirectTy); UnpaddedSize = DirectAlign = CharUnits::fromQuantity(8); @@ -7843,35 +7857,57 @@ void SystemZABIInfo::computeInfo(CGFunctionInfo &FI) const { // Check if a vararg vector argument is passed, in which case the // vector ABI becomes visible as the va_list could be passed on to // other functions. - SZCGI.handleExternallyVisibleObjABI(I.type.getTypePtr(), CGT.getCGM()); + SZCGI.handleExternallyVisibleObjABI(I.type.getTypePtr(), CGT.getCGM(), + /*IsParam*/true); } } -bool SystemZTargetCodeGenInfo::isVectorTypeBased(const Type *Ty) const { - while (Ty->isPointerType() || Ty->isArrayType()) - Ty = Ty->getPointeeOrArrayElementType(); +bool SystemZTargetCodeGenInfo::isVectorTypeBased(const Type *Ty, + bool IsParam) const { if (!SeenTypes.insert(Ty).second) return false; - if (Ty->isVectorType()) - return true; + + if (IsParam) { + // A narrow (<16 bytes) vector will as a parameter also expose the ABI as + // it will be passed in a vector register. A wide (>16 bytes) vector will + // be passed via "hidden" pointer where any extra alignment is not + // required (per GCC). + const Type *SingleEltTy = + getABIInfo().GetSingleElementType(QualType(Ty, 0)).getTypePtr(); + bool SingleVecEltStruct = SingleEltTy != Ty && SingleEltTy->isVectorType() && + Ctx.getTypeSize(SingleEltTy) == Ctx.getTypeSize(Ty); + if (Ty->isVectorType() || SingleVecEltStruct) + return Ctx.getTypeSize(Ty) / 8 <= 16; + } + + // Assume pointers are dereferenced. + while (Ty->isPointerType() || Ty->isArrayType()) + Ty = Ty->getPointeeOrArrayElementType(); + + // Vectors >= 16 bytes expose the ABI through alignment requirements. + if (Ty->isVectorType() && Ctx.getTypeSize(Ty) / 8 >= 16) + return true; + if (const auto *RecordTy = Ty->getAs<RecordType>()) { const RecordDecl *RD = RecordTy->getDecl(); if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) if (CXXRD->hasDefinition()) for (const auto &I : CXXRD->bases()) - if (isVectorTypeBased(I.getType().getTypePtr())) + if (isVectorTypeBased(I.getType().getTypePtr(), /*IsParam*/false)) return true; for (const auto *FD : RD->fields()) - if (isVectorTypeBased(FD->getType().getTypePtr())) + if (isVectorTypeBased(FD->getType().getTypePtr(), /*IsParam*/false)) return true; } + if (const auto *FT = Ty->getAs<FunctionType>()) - if (isVectorTypeBased(FT->getReturnType().getTypePtr())) + if (isVectorTypeBased(FT->getReturnType().getTypePtr(), /*IsParam*/true)) return true; if (const FunctionProtoType *Proto = Ty->getAs<FunctionProtoType>()) for (auto ParamType : Proto->getParamTypes()) - if (isVectorTypeBased(ParamType.getTypePtr())) + if (isVectorTypeBased(ParamType.getTypePtr(), /*IsParam*/true)) return true; + return false; } |
