diff options
-rw-r--r-- | include/clang/AST/ASTContext.h | 8 | ||||
-rw-r--r-- | include/clang/Basic/TargetInfo.h | 5 | ||||
-rw-r--r-- | lib/AST/ASTContext.cpp | 16 | ||||
-rw-r--r-- | lib/Basic/TargetInfo.cpp | 1 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.cpp | 10 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.h | 4 |
6 files changed, 41 insertions, 3 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 902ded55f8..c5d3337fd2 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -1593,6 +1593,14 @@ public: /// beneficial for performance to overalign a data type. unsigned getPreferredTypeAlign(const Type *T) const; + /// \brief Return the alignment in bits that should be given to a + /// global variable with type \p T. + unsigned getAlignOfGlobalVar(QualType T) const; + + /// \brief Return the alignment in characters that should be given to a + /// global variable with type \p T. + CharUnits getAlignOfGlobalVarInChars(QualType T) const; + /// \brief Return a conservative estimate of the alignment of the specified /// decl \p D. /// diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index c05f062aee..21325fac36 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -66,6 +66,7 @@ protected: unsigned char LongWidth, LongAlign; unsigned char LongLongWidth, LongLongAlign; unsigned char SuitableAlign; + unsigned char MinGlobalAlign; unsigned char MaxAtomicPromoteWidth, MaxAtomicInlineWidth; unsigned short MaxVectorAlign; const char *DescriptionString; @@ -266,6 +267,10 @@ public: /// object with a fundamental alignment requirement. unsigned getSuitableAlign() const { return SuitableAlign; } + /// getMinGlobalAlign - Return the minimum alignment of a global variable, + /// unless its alignment is explicitly reduced via attributes. + unsigned getMinGlobalAlign() const { return MinGlobalAlign; } + /// getWCharWidth/Align - Return the size of 'wchar_t' for this target, in /// bits. unsigned getWCharWidth() const { return getTypeWidth(WCharType); } diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index e6dfd445ad..8d40a6a299 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -1283,6 +1283,10 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) const { T = getBaseElementType(arrayType); } Align = std::max(Align, getPreferredTypeAlign(T.getTypePtr())); + if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { + if (VD->hasGlobalStorage()) + Align = std::max(Align, getTargetInfo().getMinGlobalAlign()); + } } // Fields can be subject to extra alignment constraints, like if @@ -1725,6 +1729,18 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) const { return ABIAlign; } +/// getAlignOfGlobalVar - Return the alignment in bits that should be given +/// to a global variable of the specified type. +unsigned ASTContext::getAlignOfGlobalVar(QualType T) const { + return std::max(getTypeAlign(T), getTargetInfo().getMinGlobalAlign()); +} + +/// getAlignOfGlobalVarInChars - Return the alignment in characters that +/// should be given to a global variable of the specified type. +CharUnits ASTContext::getAlignOfGlobalVarInChars(QualType T) const { + return toCharUnitsFromBits(getAlignOfGlobalVar(T)); +} + /// DeepCollectObjCIvars - /// This routine first collects all declared, but not synthesized, ivars in /// super class and then collects all ivars, including those synthesized for diff --git a/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp index ff72f495c8..0d44dc010e 100644 --- a/lib/Basic/TargetInfo.cpp +++ b/lib/Basic/TargetInfo.cpp @@ -37,6 +37,7 @@ TargetInfo::TargetInfo(const std::string &T) : TargetOpts(), Triple(T) LongWidth = LongAlign = 32; LongLongWidth = LongLongAlign = 64; SuitableAlign = 64; + MinGlobalAlign = 0; HalfWidth = 16; HalfAlign = 16; FloatWidth = 32; diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index ff183c96e0..0b03a3c4b6 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -2339,6 +2339,8 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) { new llvm::GlobalVariable(getModule(), C->getType(), /*isConstant=*/true, Linkage, C, ".str"); GV->setUnnamedAddr(true); + // Don't enforce the target's minimum global alignment, since the only use + // of the string is via this class initializer. if (isUTF16) { CharUnits Align = getContext().getTypeAlignInChars(getContext().ShortTy); GV->setAlignment(Align.getQuantity()); @@ -2472,6 +2474,8 @@ CodeGenModule::GetAddrOfConstantString(const StringLiteral *Literal) { new llvm::GlobalVariable(getModule(), C->getType(), isConstant, Linkage, C, ".str"); GV->setUnnamedAddr(true); + // Don't enforce the target's minimum global alignment, since the only use + // of the string is via this class initializer. CharUnits Align = getContext().getTypeAlignInChars(getContext().CharTy); GV->setAlignment(Align.getQuantity()); Fields[1] = llvm::ConstantExpr::getGetElementPtr(GV, Zeros); @@ -2576,7 +2580,7 @@ CodeGenModule::GetConstantArrayFromStringLiteral(const StringLiteral *E) { /// constant array for the given string literal. llvm::Constant * CodeGenModule::GetAddrOfConstantStringFromLiteral(const StringLiteral *S) { - CharUnits Align = getContext().getTypeAlignInChars(S->getType()); + CharUnits Align = getContext().getAlignOfGlobalVarInChars(S->getType()); if (S->isAscii() || S->isUTF8()) { SmallString<64> Str(S->getString()); @@ -2645,6 +2649,10 @@ llvm::Constant *CodeGenModule::GetAddrOfConstantString(StringRef Str, if (!GlobalName) GlobalName = ".str"; + if (Alignment == 0) + Alignment = getContext().getAlignOfGlobalVarInChars(getContext().CharTy) + .getQuantity(); + // Don't share any string literals if strings aren't constant. if (LangOpts.WritableStrings) return GenerateStringLiteral(Str, false, *this, GlobalName, Alignment); diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 7bbca80bf4..91138c607c 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -713,7 +713,7 @@ public: /// (if one is created). llvm::Constant *GetAddrOfConstantString(StringRef Str, const char *GlobalName=0, - unsigned Alignment=1); + unsigned Alignment=0); /// GetAddrOfConstantCString - Returns a pointer to a character array /// containing the literal and a terminating '\0' character. The result has @@ -723,7 +723,7 @@ public: /// created). llvm::Constant *GetAddrOfConstantCString(const std::string &str, const char *GlobalName=0, - unsigned Alignment=1); + unsigned Alignment=0); /// GetAddrOfConstantCompoundLiteral - Returns a pointer to a constant global /// variable for the given file-scope compound literal expression. |