From 6ec3668a2608b63473207319f5ceff9bbd22ea51 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Wed, 18 Feb 2009 23:53:56 +0000 Subject: [PATCH] Address Chris's comments regarding C++ name mangling. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64984 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGDecl.cpp | 4 +-- lib/CodeGen/CGExpr.cpp | 2 +- lib/CodeGen/CodeGenFunction.cpp | 3 +-- lib/CodeGen/CodeGenModule.cpp | 22 ++++++++------- lib/CodeGen/CodeGenModule.h | 28 ++++++++++++------- lib/CodeGen/Mangle.cpp | 48 +++++++++++++++++++-------------- lib/CodeGen/Mangle.h | 2 +- 7 files changed, 64 insertions(+), 45 deletions(-) diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index f2fec65cc3..56e7b8b792 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -106,7 +106,7 @@ CodeGenFunction::GenerateStaticBlockVarDecl(const VarDecl &D, std::string ContextName; if (const FunctionDecl *FD = dyn_cast(CurFuncDecl)) - ContextName = CGM.getMangledName(FD)->getName(); + ContextName = CGM.getMangledName(FD); else if (isa(CurFuncDecl)) ContextName = std::string(CurFn->getNameStart(), CurFn->getNameStart() + CurFn->getNameLen()); @@ -171,7 +171,7 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) { // A normal fixed sized variable becomes an alloca in the entry block. const llvm::Type *LTy = ConvertType(Ty); llvm::AllocaInst *Alloc = - CreateTempAlloca(LTy, CGM.getMangledName(&D)->getName()); + CreateTempAlloca(LTy, CGM.getMangledName(&D)); unsigned align = getContext().getTypeAlign(Ty); if (const AlignedAttr* AA = D.getAttr()) align = std::max(align, AA->getAlignment()); diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index e991c8ec77..69429e08e6 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -702,7 +702,7 @@ LValue CodeGenFunction::EmitPredefinedFunctionName(unsigned Type) { std::string FunctionName; if(const FunctionDecl *FD = dyn_cast(CurFuncDecl)) { - FunctionName = CGM.getMangledName(FD)->getName(); + FunctionName = CGM.getMangledName(FD); } else { // Just get the mangled name. FunctionName = CurFn->getName(); diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index a699317f63..c1436b5ff4 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -171,8 +171,7 @@ void CodeGenFunction::StartFunction(const Decl *D, QualType RetTy, if (CGDebugInfo *DI = getDebugInfo()) { DI->setLocation(StartLoc); if (const FunctionDecl *FD = dyn_cast(D)) { - DI->EmitFunctionStart(CGM.getMangledName(FD)->getName(), - RetTy, CurFn, Builder); + DI->EmitFunctionStart(CGM.getMangledName(FD), RetTy, CurFn, Builder); } else { // Just use LLVM function name. DI->EmitFunctionStart(Fn->getName().c_str(), diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index e7c784580b..ca6ba14f85 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -170,13 +170,15 @@ static void setGlobalVisibility(llvm::GlobalValue *GV, /// FIXME: Performance here is going to be terribly until we start /// caching mangled names. However, we should fix the problem above /// first. -IdentifierInfo *CodeGenModule::getMangledName(const NamedDecl *ND) const { - std::string Name; - llvm::raw_string_ostream Out(Name); +const char *CodeGenModule::getMangledName(const NamedDecl *ND) { + llvm::SmallString<256> Name; + llvm::raw_svector_ostream Out(Name); if (!mangleName(ND, Context, Out)) - return ND->getIdentifier(); + return ND->getIdentifier()->getName(); - return &Context.Idents.get(Out.str()); + Name += '\0'; + return MangledNames.GetOrCreateValue(Name.begin(), Name.end()) + .getKeyData(); } /// AddGlobalCtor - Add a function to the list that will be called before @@ -379,7 +381,7 @@ void CodeGenModule::EmitAliases() { llvm::GlobalValue *GA = new llvm::GlobalAlias(aliasee->getType(), llvm::Function::ExternalLinkage, - getMangledName(D)->getName(), aliasee, + getMangledName(D), aliasee, &getModule()); llvm::GlobalValue *&Entry = GlobalDeclMap[getMangledName(D)]; @@ -582,7 +584,7 @@ void CodeGenModule::EmitGlobalDefinition(const ValueDecl *D) { llvm::GlobalVariable *GV = new llvm::GlobalVariable(Ty, false, llvm::GlobalValue::ExternalLinkage, - 0, getMangledName(D)->getName(), &getModule(), + 0, getMangledName(D), &getModule(), 0, ASTTy.getAddressSpace()); Entry = GV; @@ -630,7 +632,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { if (!GV) { GV = new llvm::GlobalVariable(InitType, false, llvm::GlobalValue::ExternalLinkage, - 0, getMangledName(D)->getName(), + 0, getMangledName(D), &getModule(), 0, ASTTy.getAddressSpace()); } else if (GV->getType() != llvm::PointerType::get(InitType, ASTTy.getAddressSpace())) { @@ -654,7 +656,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { // Make a new global with the correct type GV = new llvm::GlobalVariable(InitType, false, llvm::GlobalValue::ExternalLinkage, - 0, getMangledName(D)->getName(), + 0, getMangledName(D), &getModule(), 0, ASTTy.getAddressSpace()); // Steal the name of the old global GV->takeName(OldGV); @@ -753,7 +755,7 @@ CodeGenModule::EmitForwardFunctionDefinition(const FunctionDecl *D) { const llvm::Type *Ty = getTypes().ConvertType(D->getType()); llvm::Function *F = llvm::Function::Create(cast(Ty), llvm::Function::ExternalLinkage, - getMangledName(D)->getName(), + getMangledName(D), &getModule()); SetFunctionAttributes(D, F); return F; diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index b54ee13df6..24453ccadc 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -18,6 +18,7 @@ #include "clang/AST/Attr.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringSet.h" #include "CGCall.h" @@ -81,14 +82,23 @@ class CodeGenModule { /// will name them and patch up conflicts when we release the module. std::vector< std::pair > RuntimeFunctions; - /// GlobalDeclMap - Mapping of decl names global variables we have already - /// emitted. Note that the entries in this map are the actual globals and - /// therefore may not be of the same type as the decl, they should be - /// bitcasted on retrieval. Also note that the globals are keyed on their - /// source name, not the global name (which may change with attributes such as - /// asm-labels). This key to this map should be generated using - /// getMangledName(). - llvm::DenseMap GlobalDeclMap; + /// GlobalDeclMap - Mapping of decl names (represented as unique + /// character pointers from either the identifier table or the set + /// of mangled names) to global variables we have already + /// emitted. Note that the entries in this map are the actual + /// globals and therefore may not be of the same type as the decl, + /// they should be bitcasted on retrieval. Also note that the + /// globals are keyed on their source name, not the global name + /// (which may change with attributes such as asm-labels). This key + /// to this map should be generated using getMangledName(). + llvm::DenseMap GlobalDeclMap; + + /// \brief Contains the strings used for mangled names. + /// + /// FIXME: Eventually, this should map from the semantic/canonical + /// declaration for each global entity to its mangled name (if it + /// has one). + llvm::StringSet<> MangledNames; /// Aliases - List of aliases in module. These cannot be emitted until all the /// code has been seen, as they reference things by name instead of directly @@ -285,7 +295,7 @@ public: const Decl *TargetDecl, AttributeListType &PAL); - IdentifierInfo *getMangledName(const NamedDecl *ND) const; + const char *getMangledName(const NamedDecl *ND); private: diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp index 9ad98d787a..f007539714 100644 --- a/lib/CodeGen/Mangle.cpp +++ b/lib/CodeGen/Mangle.cpp @@ -1,4 +1,4 @@ -//===--------------------- Mangle.cpp - Mangle C++ Names ------------------===// +//===--- Mangle.cpp - Mangle C++ Names --------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -18,6 +18,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" +#include "clang/Basic/SourceManager.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/raw_ostream.h" using namespace clang; @@ -61,17 +62,28 @@ bool CXXNameMangler::mangle(const NamedDecl *D) { // FIXME: Actually use a visitor to decode these? if (const FunctionDecl *FD = dyn_cast(D)) { bool RequiresMangling = false; - // Clang's "overloadable" attribute extension to C/C++ - if (FD->getAttr()) + // No mangled in an "implicit extern C" header. + if (Context.getSourceManager().getFileCharacteristic(FD->getLocation()) + == SrcMgr::C_ExternCSystem) + RequiresMangling = false; + // Clang's "overloadable" attribute extension to C/C++ implies + // name mangling (always). + else if (FD->getAttr()) RequiresMangling = true; else if (Context.getLangOptions().CPlusPlus) { + // C++ requires name mangling, unless we're in a C linkage + // specification. RequiresMangling = true; - if (isa(FD->getDeclContext()) && - cast(FD->getDeclContext())->getLanguage() - == LinkageSpecDecl::lang_c) { - // Entities with C linkage are not mangled. - RequiresMangling = false; - } + + for (const DeclContext *DC = FD->getDeclContext(); + !DC->isTranslationUnit(); DC = DC->getParent()) { + if (const LinkageSpecDecl *Linkage = dyn_cast(DC)) { + // extern "C" functions don't use name mangling + if (Linkage->getLanguage() == LinkageSpecDecl::lang_c) + RequiresMangling = false; + break; + } + } } if (RequiresMangling) { @@ -95,15 +107,7 @@ static bool isStdNamespace(const DeclContext *DC) { return false; const NamespaceDecl *NS = cast(DC); - const IdentifierInfo *Name = NS->getIdentifier(); - if (Name->getLength() != 3) - return false; - - const char *Str = Name->getName(); - if (Str[0] != 's' || Str[1] != 't' || Str[2] != 'd') - return false; - - return true; + return NS->getOriginalNamespace()->getIdentifier()->isStr("std"); } void CXXNameMangler::mangleName(const NamedDecl *ND) { @@ -307,7 +311,7 @@ CXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity) { case OO_None: case NUM_OVERLOADED_OPERATORS: - assert(false && "Not an ovelroaded operator"); + assert(false && "Not an overloaded operator"); break; } } @@ -516,7 +520,11 @@ namespace clang { bool mangleName(const NamedDecl *D, ASTContext &Context, llvm::raw_ostream &os) { CXXNameMangler Mangler(Context, os); - return Mangler.mangle(D); + if (!Mangler.mangle(D)) + return false; + + os.flush(); + return true; } } diff --git a/lib/CodeGen/Mangle.h b/lib/CodeGen/Mangle.h index 404f8bddb7..60a5113ccc 100644 --- a/lib/CodeGen/Mangle.h +++ b/lib/CodeGen/Mangle.h @@ -1,4 +1,4 @@ -//===---------------------- Mangle.h - Mangle C++ Names -------------------===// +//===--- Mangle.h - Mangle C++ Names ----------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // -- 2.40.0