diff options
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 78 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.h | 5 |
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; |