From 58e5bee17aa1a0ea0c690f9909f5522541e17f95 Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Mon, 24 Mar 2014 21:43:36 +0000 Subject: 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. Further, we avoid doing this if either -fwritable-strings or -fsanitize=address are present. This reverts commit r204596. llvm-svn: 204675 --- clang/lib/CodeGen/CodeGenModule.cpp | 78 ++++++++++++++++++++++++++++--------- 1 file changed, 60 insertions(+), 18 deletions(-) (limited to 'clang/lib/CodeGen/CodeGenModule.cpp') diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 53e7d56..c0fbdbe 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 *Entry = nullptr; + llvm::GlobalVariable *GV = nullptr; + if (!LangOpts.WritableStrings) { + llvm::StringMap *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) { + SmallString<256> MangledNameBuffer; + StringRef GlobalVariableName; + llvm::GlobalValue::LinkageTypes LT; + + // Mangle the string literal if the ABI allows for it. However, we cannot + // do this if we are compiling with ASan or -fwritable-strings because they + // rely on strings having normal linkage. + if (!LangOpts.WritableStrings && !SanOpts.Address && + getCXXABI().getMangleContext().shouldMangleStringLiteral(S)) { + llvm::raw_svector_ostream Out(MangledNameBuffer); + getCXXABI().getMangleContext().mangleStringLiteral(S, Out); + Out.flush(); + + LT = llvm::GlobalValue::LinkOnceODRLinkage; + GlobalVariableName = MangledNameBuffer; + } 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 &Entry = - ConstantStringMap.GetOrCreateValue(Str); + Constant1ByteStringMap.GetOrCreateValue(Str); if (llvm::GlobalVariable *GV = Entry.getValue()) { if (Alignment > GV->getAlignment()) { -- cgit v1.1