summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
authorDavid Majnemer <david.majnemer@gmail.com>2014-03-23 17:47:16 +0000
committerDavid Majnemer <david.majnemer@gmail.com>2014-03-23 17:47:16 +0000
commit3843a05edf07d787dac26b81146f25c83d5e5d8d (patch)
tree131d34c83ebfc5d8e851826c5070f76e0c276798 /clang/lib/CodeGen
parentfb744589bc493855e6777ba16637ae9164d60da1 (diff)
downloadbcm5719-llvm-3843a05edf07d787dac26b81146f25c83d5e5d8d.tar.gz
bcm5719-llvm-3843a05edf07d787dac26b81146f25c83d5e5d8d.zip
MS ABI: Eliminate Duplicate Strings
COFF doesn't have mergeable sections so LLVM/clang's normal tactics for string deduplication will not have any effect. To remedy this we place each string inside it's own section and mark the section as IMAGE_COMDAT_SELECT_ANY. However, we can only do this if the string has an external name that we can generate from it's contents. To be compatible with MSVC, we must use their scheme. Otherwise identical strings in translation units from clang may not be deduplicated with translation units in MSVC. This fixes PR18248. N.B. We will not attempt to do anything with a string literal which is not of type 'char' or 'wchar_t' because their compiler does not support unicode string literals as of this date. llvm-svn: 204562
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/CodeGenModule.cpp78
-rw-r--r--clang/lib/CodeGen/CodeGenModule.h5
2 files changed, 64 insertions, 19 deletions
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 53e7d56a8d9..097e30c71d1 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -2572,25 +2572,67 @@ CodeGenModule::GetConstantArrayFromStringLiteral(const StringLiteral *E) {
llvm::Constant *
CodeGenModule::GetAddrOfConstantStringFromLiteral(const StringLiteral *S) {
CharUnits Align = getContext().getAlignOfGlobalVarInChars(S->getType());
- if (S->isAscii() || S->isUTF8()) {
- SmallString<64> Str(S->getString());
-
- // Resize the string to the right size, which is indicated by its type.
- const ConstantArrayType *CAT = Context.getAsConstantArrayType(S->getType());
- Str.resize(CAT->getSize().getZExtValue());
- return GetAddrOfConstantString(Str, /*GlobalName*/ 0, Align.getQuantity());
+
+ llvm::StringMapEntry<llvm::GlobalVariable *> *Entry = nullptr;
+ llvm::GlobalVariable *GV = nullptr;
+ if (!LangOpts.WritableStrings) {
+ llvm::StringMap<llvm::GlobalVariable *> *ConstantStringMap = nullptr;
+ switch (S->getCharByteWidth()) {
+ case 1:
+ ConstantStringMap = &Constant1ByteStringMap;
+ break;
+ case 2:
+ ConstantStringMap = &Constant2ByteStringMap;
+ break;
+ case 4:
+ ConstantStringMap = &Constant4ByteStringMap;
+ break;
+ default:
+ llvm_unreachable("unhandled byte width!");
+ }
+ Entry = &ConstantStringMap->GetOrCreateValue(S->getBytes());
+ GV = Entry->getValue();
+ }
+
+ if (!GV) {
+ StringRef GlobalVariableName;
+ llvm::GlobalValue::LinkageTypes LT;
+ if (!LangOpts.WritableStrings &&
+ getCXXABI().getMangleContext().shouldMangleStringLiteral(S)) {
+ LT = llvm::GlobalValue::LinkOnceODRLinkage;
+
+ SmallString<256> Buffer;
+ llvm::raw_svector_ostream Out(Buffer);
+ getCXXABI().getMangleContext().mangleStringLiteral(S, Out);
+ Out.flush();
+
+ size_t Length = Buffer.size();
+ char *Name = MangledNamesAllocator.Allocate<char>(Length);
+ std::copy(Buffer.begin(), Buffer.end(), Name);
+ GlobalVariableName = StringRef(Name, Length);
+ } else {
+ LT = llvm::GlobalValue::PrivateLinkage;;
+ GlobalVariableName = ".str";
+ }
+
+ // OpenCL v1.2 s6.5.3: a string literal is in the constant address space.
+ unsigned AddrSpace = 0;
+ if (getLangOpts().OpenCL)
+ AddrSpace = getContext().getTargetAddressSpace(LangAS::opencl_constant);
+
+ llvm::Constant *C = GetConstantArrayFromStringLiteral(S);
+ GV = new llvm::GlobalVariable(
+ getModule(), C->getType(), !LangOpts.WritableStrings, LT, C,
+ GlobalVariableName, /*InsertBefore=*/nullptr,
+ llvm::GlobalVariable::NotThreadLocal, AddrSpace);
+ GV->setUnnamedAddr(true);
+ if (Entry)
+ Entry->setValue(GV);
}
- // FIXME: the following does not memoize wide strings.
- llvm::Constant *C = GetConstantArrayFromStringLiteral(S);
- llvm::GlobalVariable *GV =
- new llvm::GlobalVariable(getModule(),C->getType(),
- !LangOpts.WritableStrings,
- llvm::GlobalValue::PrivateLinkage,
- C,".str");
+ if (Align.getQuantity() > GV->getAlignment())
+ GV->setAlignment(Align.getQuantity());
- GV->setAlignment(Align.getQuantity());
- GV->setUnnamedAddr(true);
return GV;
}
@@ -2615,7 +2657,7 @@ static llvm::GlobalVariable *GenerateStringLiteral(StringRef str,
llvm::Constant *C =
llvm::ConstantDataArray::getString(CGM.getLLVMContext(), str, false);
- // OpenCL v1.1 s6.5.3: a string literal is in the constant address space.
+ // OpenCL v1.2 s6.5.3: a string literal is in the constant address space.
unsigned AddrSpace = 0;
if (CGM.getLangOpts().OpenCL)
AddrSpace = CGM.getContext().getTargetAddressSpace(LangAS::opencl_constant);
@@ -2654,7 +2696,7 @@ llvm::Constant *CodeGenModule::GetAddrOfConstantString(StringRef Str,
return GenerateStringLiteral(Str, false, *this, GlobalName, Alignment);
llvm::StringMapEntry<llvm::GlobalVariable *> &Entry =
- ConstantStringMap.GetOrCreateValue(Str);
+ Constant1ByteStringMap.GetOrCreateValue(Str);
if (llvm::GlobalVariable *GV = Entry.getValue()) {
if (Alignment > GV->getAlignment()) {
diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h
index 4bd8b7a3de7..7694eed1a1b 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -319,7 +319,10 @@ class CodeGenModule : public CodeGenTypeCache {
llvm::StringMap<llvm::Constant*> AnnotationStrings;
llvm::StringMap<llvm::Constant*> CFConstantStringMap;
- llvm::StringMap<llvm::GlobalVariable*> ConstantStringMap;
+
+ llvm::StringMap<llvm::GlobalVariable *> Constant1ByteStringMap;
+ llvm::StringMap<llvm::GlobalVariable *> Constant2ByteStringMap;
+ llvm::StringMap<llvm::GlobalVariable *> Constant4ByteStringMap;
llvm::DenseMap<const Decl*, llvm::Constant *> StaticLocalDeclMap;
llvm::DenseMap<const Decl*, llvm::GlobalVariable*> StaticLocalDeclGuardMap;
llvm::DenseMap<const Expr*, llvm::Constant *> MaterializedGlobalTemporaryMap;
OpenPOWER on IntegriCloud