From c54a9c3b7aa1b0f857ee866d3aae71f1d7884d6a Mon Sep 17 00:00:00 2001 From: Alexey Samsonov Date: Wed, 4 Jun 2014 19:56:57 +0000 Subject: [PATCH] Refactor and generalize GetAddrOfConstantString and GetAddrOfConstantStringFromLiteral. Share mode code between these functions and re-structure them in a way which shows how similar they actually are. The latter function works well with literals of multi-byte chars and does a GlobalVariable name mangling (if global strings are non-writable). No functionality change. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@210212 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CodeGenModule.cpp | 179 ++++++++++++++++------------------ lib/CodeGen/CodeGenModule.h | 3 + 2 files changed, 87 insertions(+), 95 deletions(-) diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 44ee1e0f6a..8f728a4a38 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -2686,72 +2686,65 @@ CodeGenModule::GetConstantArrayFromStringLiteral(const StringLiteral *E) { return llvm::ConstantDataArray::get(VMContext, Elements); } +static llvm::GlobalVariable * +GenerateStringLiteral(llvm::Constant *C, llvm::GlobalValue::LinkageTypes LT, + CodeGenModule &CGM, StringRef GlobalName, + unsigned Alignment) { + // 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); + + // Create a global variable for this string + auto *GV = new llvm::GlobalVariable( + CGM.getModule(), C->getType(), !CGM.getLangOpts().WritableStrings, LT, C, + GlobalName, nullptr, llvm::GlobalVariable::NotThreadLocal, AddrSpace); + GV->setAlignment(Alignment); + GV->setUnnamedAddr(true); + return GV; +} + /// GetAddrOfConstantStringFromLiteral - Return a pointer to a /// constant array for the given string literal. llvm::Constant * CodeGenModule::GetAddrOfConstantStringFromLiteral(const StringLiteral *S) { - CharUnits Align = getContext().getAlignOfGlobalVarInChars(S->getType()); + auto Alignment = + getContext().getAlignOfGlobalVarInChars(S->getType()).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 = getConstantStringMapEntry(S->getBytes(), S->getCharByteWidth()); + if (auto GV = Entry->getValue()) { + if (Alignment > GV->getAlignment()) + GV->setAlignment(Alignment); + return GV; } - 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"; - } + SmallString<256> MangledNameBuffer; + StringRef GlobalVariableName; + llvm::GlobalValue::LinkageTypes LT; - // 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); + // 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(); - 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); + LT = llvm::GlobalValue::LinkOnceODRLinkage; + GlobalVariableName = MangledNameBuffer; + } else { + LT = llvm::GlobalValue::PrivateLinkage; + GlobalVariableName = ".str"; } - if (Align.getQuantity() > GV->getAlignment()) - GV->setAlignment(Align.getQuantity()); - + llvm::Constant *C = GetConstantArrayFromStringLiteral(S); + auto GV = GenerateStringLiteral(C, LT, *this, GlobalVariableName, Alignment); + if (Entry) + Entry->setValue(GV); return GV; } @@ -2766,29 +2759,23 @@ CodeGenModule::GetAddrOfConstantStringFromObjCEncode(const ObjCEncodeExpr *E) { } -/// GenerateWritableString -- Creates storage for a string literal. -static llvm::GlobalVariable *GenerateStringLiteral(StringRef str, - bool constant, - CodeGenModule &CGM, - const char *GlobalName, - unsigned Alignment) { - // Create Constant for this string literal. Don't add a '\0'. - llvm::Constant *C = - llvm::ConstantDataArray::getString(CGM.getLLVMContext(), str, false); - - // 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); - - // Create a global variable for this string - auto *GV = new llvm::GlobalVariable( - CGM.getModule(), C->getType(), constant, - llvm::GlobalValue::PrivateLinkage, C, GlobalName, nullptr, - llvm::GlobalVariable::NotThreadLocal, AddrSpace); - GV->setAlignment(Alignment); - GV->setUnnamedAddr(true); - return GV; +llvm::StringMapEntry *CodeGenModule::getConstantStringMapEntry( + StringRef Str, int CharByteWidth) { + llvm::StringMap *ConstantStringMap = nullptr; + switch (CharByteWidth) { + case 1: + ConstantStringMap = &Constant1ByteStringMap; + break; + case 2: + ConstantStringMap = &Constant2ByteStringMap; + break; + case 4: + ConstantStringMap = &Constant4ByteStringMap; + break; + default: + llvm_unreachable("unhandled byte width!"); + } + return &ConstantStringMap->GetOrCreateValue(Str); } /// GetAddrOfConstantString - Returns a pointer to a character array @@ -2802,32 +2789,34 @@ static llvm::GlobalVariable *GenerateStringLiteral(StringRef str, llvm::Constant *CodeGenModule::GetAddrOfConstantString(StringRef Str, const char *GlobalName, unsigned Alignment) { - // Get the default prefix if a name wasn't specified. - if (!GlobalName) - GlobalName = ".str"; - - if (Alignment == 0) - Alignment = getContext().getAlignOfGlobalVarInChars(getContext().CharTy) - .getQuantity(); + 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); - - llvm::StringMapEntry &Entry = - Constant1ByteStringMap.GetOrCreateValue(Str); - - if (llvm::GlobalVariable *GV = Entry.getValue()) { - if (Alignment > GV->getAlignment()) { - GV->setAlignment(Alignment); + llvm::StringMapEntry *Entry = nullptr; + if (!LangOpts.WritableStrings) { + Entry = getConstantStringMapEntry(Str, 1); + if (auto GV = Entry->getValue()) { + if (Alignment > GV->getAlignment()) + GV->setAlignment(Alignment); + return GV; } - return GV; } + // Create Constant for this string literal. Don't add a '\0'. + llvm::Constant *C = + llvm::ConstantDataArray::getString(getLLVMContext(), Str, false); + // Get the default prefix if a name wasn't specified. + if (!GlobalName) + GlobalName = ".str"; // Create a global variable for this. - llvm::GlobalVariable *GV = GenerateStringLiteral(Str, true, *this, GlobalName, - Alignment); - Entry.setValue(GV); + auto GV = GenerateStringLiteral(C, llvm::GlobalValue::PrivateLinkage, *this, + GlobalName, Alignment); + if (Entry) + Entry->setValue(GV); return GV; } diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index ef18957e3d..cbc81ff6fe 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -1032,6 +1032,9 @@ private: llvm::PointerType *PTy, const VarDecl *D); + llvm::StringMapEntry * + getConstantStringMapEntry(StringRef Str, int CharByteWidth); + /// Set attributes which are common to any form of a global definition (alias, /// Objective-C method, function, global variable). /// -- 2.40.0