diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 6651282384eb..5341f22ab970 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1923,7 +1923,10 @@ llvm::Constant * CodeGenModule::GetAddrOfConstantStringFromLiteral(const StringLiteral *S) { // FIXME: This can be more efficient. // FIXME: We shouldn't need to bitcast the constant in the wide string case. - llvm::Constant *C = GetAddrOfConstantString(GetStringForStringLiteral(S)); + CharUnits Align = getContext().getTypeAlignInChars(S->getType()); + llvm::Constant *C = GetAddrOfConstantString(GetStringForStringLiteral(S), + /* GlobalName */ 0, + Align.getQuantity()); if (S->isWide() || S->isUTF16() || S->isUTF32()) { llvm::Type *DestTy = llvm::PointerType::getUnqual(getTypes().ConvertType(S->getType())); @@ -1944,10 +1947,11 @@ CodeGenModule::GetAddrOfConstantStringFromObjCEncode(const ObjCEncodeExpr *E) { /// GenerateWritableString -- Creates storage for a string literal. -static llvm::Constant *GenerateStringLiteral(StringRef str, +static llvm::GlobalVariable *GenerateStringLiteral(StringRef str, bool constant, CodeGenModule &CGM, - const char *GlobalName) { + const char *GlobalName, + unsigned Alignment) { // Create Constant for this string literal. Don't add a '\0'. llvm::Constant *C = llvm::ConstantArray::get(CGM.getLLVMContext(), str, false); @@ -1957,7 +1961,7 @@ static llvm::Constant *GenerateStringLiteral(StringRef str, new llvm::GlobalVariable(CGM.getModule(), C->getType(), constant, llvm::GlobalValue::PrivateLinkage, C, GlobalName); - GV->setAlignment(1); + GV->setAlignment(Alignment); GV->setUnnamedAddr(true); return GV; } @@ -1971,7 +1975,8 @@ static llvm::Constant *GenerateStringLiteral(StringRef str, /// /// The result has pointer to array type. llvm::Constant *CodeGenModule::GetAddrOfConstantString(StringRef Str, - const char *GlobalName) { + const char *GlobalName, + unsigned Alignment) { bool IsConstant = !Features.WritableStrings; // Get the default prefix if a name wasn't specified. @@ -1980,27 +1985,32 @@ llvm::Constant *CodeGenModule::GetAddrOfConstantString(StringRef Str, // Don't share any string literals if strings aren't constant. if (!IsConstant) - return GenerateStringLiteral(Str, false, *this, GlobalName); + return GenerateStringLiteral(Str, false, *this, GlobalName, Alignment); - llvm::StringMapEntry &Entry = + llvm::StringMapEntry &Entry = ConstantStringMap.GetOrCreateValue(Str); - if (Entry.getValue()) - return Entry.getValue(); + if (llvm::GlobalVariable *GV = Entry.getValue()) { + if (Alignment > GV->getAlignment()) { + GV->setAlignment(Alignment); + } + return GV; + } // Create a global variable for this. - llvm::Constant *C = GenerateStringLiteral(Str, true, *this, GlobalName); - Entry.setValue(C); - return C; + llvm::GlobalVariable *GV = GenerateStringLiteral(Str, true, *this, GlobalName, Alignment); + Entry.setValue(GV); + return GV; } /// GetAddrOfConstantCString - Returns a pointer to a character /// array containing the literal and a terminating '\0' /// character. The result has pointer to array type. llvm::Constant *CodeGenModule::GetAddrOfConstantCString(const std::string &Str, - const char *GlobalName){ + const char *GlobalName, + unsigned Alignment) { StringRef StrWithNull(Str.c_str(), Str.size() + 1); - return GetAddrOfConstantString(StrWithNull, GlobalName); + return GetAddrOfConstantString(StrWithNull, GlobalName, Alignment); } /// EmitObjCPropertyImplementations - Emit information for synthesized diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index 318c3ea2638d..ca72230559e0 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -263,7 +263,7 @@ class CodeGenModule : public CodeGenTypeCache { std::vector Annotations; llvm::StringMap CFConstantStringMap; - llvm::StringMap ConstantStringMap; + llvm::StringMap ConstantStringMap; llvm::DenseMap StaticLocalDeclMap; /// CXXGlobalInits - Global variables with initializers that need to run @@ -545,7 +545,8 @@ public: /// \param GlobalName If provided, the name to use for the global /// (if one is created). llvm::Constant *GetAddrOfConstantString(StringRef Str, - const char *GlobalName=0); + const char *GlobalName=0, + unsigned Alignment=1); /// GetAddrOfConstantCString - Returns a pointer to a character array /// containing the literal and a terminating '\0' character. The result has @@ -554,7 +555,8 @@ public: /// \param GlobalName If provided, the name to use for the global (if one is /// created). llvm::Constant *GetAddrOfConstantCString(const std::string &str, - const char *GlobalName=0); + const char *GlobalName=0, + unsigned Alignment=1); /// GetAddrOfCXXConstructor - Return the address of the constructor of the /// given type. diff --git a/clang/test/CodeGen/string-literal.c b/clang/test/CodeGen/string-literal.c index 761530f5fb5c..dfa609fe8a39 100644 --- a/clang/test/CodeGen/string-literal.c +++ b/clang/test/CodeGen/string-literal.c @@ -14,26 +14,26 @@ int main() { // CHECK-CPP0X: internal unnamed_addr constant [10 x i8] c"\E1\84\A0\C8\A0\F4\82\80\B0\00", align 1 char b[10] = "\u1120\u0220\U00102030"; - // CHECK-C: private unnamed_addr constant [12 x i8] c"A\00\00\00B\00\00\00\00\00\00\00", align 1 - // CHECK-CPP0X: private unnamed_addr constant [12 x i8] c"A\00\00\00B\00\00\00\00\00\00\00", align 1 + // CHECK-C: private unnamed_addr constant [12 x i8] c"A\00\00\00B\00\00\00\00\00\00\00", align 4 + // CHECK-CPP0X: private unnamed_addr constant [12 x i8] c"A\00\00\00B\00\00\00\00\00\00\00", align 4 const wchar_t *foo = L"AB"; - // CHECK-C: private unnamed_addr constant [12 x i8] c"4\12\00\00\0B\F0\10\00\00\00\00\00", align 1 - // CHECK-CPP0X: private unnamed_addr constant [12 x i8] c"4\12\00\00\0B\F0\10\00\00\00\00\00", align 1 + // CHECK-C: private unnamed_addr constant [12 x i8] c"4\12\00\00\0B\F0\10\00\00\00\00\00", align 4 + // CHECK-CPP0X: private unnamed_addr constant [12 x i8] c"4\12\00\00\0B\F0\10\00\00\00\00\00", align 4 const wchar_t *bar = L"\u1234\U0010F00B"; #if __cplusplus >= 201103L - // CHECK-CPP0X: private unnamed_addr constant [12 x i8] c"C\00\00\00D\00\00\00\00\00\00\00", align 1 + // CHECK-CPP0X: private unnamed_addr constant [12 x i8] c"C\00\00\00D\00\00\00\00\00\00\00", align 4 const char32_t *c = U"CD"; - // CHECK-CPP0X: private unnamed_addr constant [12 x i8] c"5\12\00\00\0C\F0\10\00\00\00\00\00", align 1 + // CHECK-CPP0X: private unnamed_addr constant [12 x i8] c"5\12\00\00\0C\F0\10\00\00\00\00\00", align 4 const char32_t *d = U"\u1235\U0010F00C"; - // CHECK-CPP0X: private unnamed_addr constant [6 x i8] c"E\00F\00\00\00", align 1 + // CHECK-CPP0X: private unnamed_addr constant [6 x i8] c"E\00F\00\00\00", align 2 const char16_t *e = u"EF"; // This should convert to utf16. - // CHECK-CPP0X: private unnamed_addr constant [10 x i8] c" \11 \02\C8\DB0\DC\00\00", align 1 + // CHECK-CPP0X: private unnamed_addr constant [10 x i8] c" \11 \02\C8\DB0\DC\00\00", align 2 const char16_t *f = u"\u1120\u0220\U00102030"; // CHECK-CPP0X: private unnamed_addr constant [4 x i8] c"def\00", align 1