diff options
author | dim <dim@FreeBSD.org> | 2014-03-21 17:53:59 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2014-03-21 17:53:59 +0000 |
commit | 9cedb8bb69b89b0f0c529937247a6a80cabdbaec (patch) | |
tree | c978f0e9ec1ab92dc8123783f30b08a7fd1e2a39 /contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp | |
parent | 03fdc2934eb61c44c049a02b02aa974cfdd8a0eb (diff) | |
download | FreeBSD-src-9cedb8bb69b89b0f0c529937247a6a80cabdbaec.zip FreeBSD-src-9cedb8bb69b89b0f0c529937247a6a80cabdbaec.tar.gz |
MFC 261991:
Upgrade our copy of llvm/clang to 3.4 release. This version supports
all of the features in the current working draft of the upcoming C++
standard, provisionally named C++1y.
The code generator's performance is greatly increased, and the loop
auto-vectorizer is now enabled at -Os and -O2 in addition to -O3. The
PowerPC backend has made several major improvements to code generation
quality and compile time, and the X86, SPARC, ARM32, Aarch64 and SystemZ
backends have all seen major feature work.
Release notes for llvm and clang can be found here:
<http://llvm.org/releases/3.4/docs/ReleaseNotes.html>
<http://llvm.org/releases/3.4/tools/clang/docs/ReleaseNotes.html>
MFC 262121 (by emaste):
Update lldb for clang/llvm 3.4 import
This commit largely restores the lldb source to the upstream r196259
snapshot with the addition of threaded inferior support and a few bug
fixes.
Specific upstream lldb revisions restored include:
SVN git
181387 779e6ac
181703 7bef4e2
182099 b31044e
182650 f2dcf35
182683 0d91b80
183862 15c1774
183929 99447a6
184177 0b2934b
184948 4dc3761
184954 007e7bc
186990 eebd175
Sponsored by: DARPA, AFRL
MFC 262186 (by emaste):
Fix mismerge in r262121
A break statement was lost in the merge. The error had no functional
impact, but restore it to reduce the diff against upstream.
MFC 262303:
Pull in r197521 from upstream clang trunk (by rdivacky):
Use the integrated assembler by default on FreeBSD/ppc and ppc64.
Requested by: jhibbits
MFC 262611:
Pull in r196874 from upstream llvm trunk:
Fix a crash that occurs when PWD is invalid.
MCJIT needs to be able to run in hostile environments, even when PWD
is invalid. There's no need to crash MCJIT in this case.
The obvious fix is to simply leave MCContext's CompilationDir empty
when PWD can't be determined. This way, MCJIT clients,
and other clients that link with LLVM don't need a valid working directory.
If we do want to guarantee valid CompilationDir, that should be done
only for clients of getCompilationDir(). This is as simple as checking
for an empty string.
The only current use of getCompilationDir is EmitGenDwarfInfo, which
won't conceivably run with an invalid working dir. However, in the
purely hypothetically and untestable case that this happens, the
AT_comp_dir will be omitted from the compilation_unit DIE.
This should help fix assertions occurring with ports-mgmt/tinderbox,
when it is using jails, and sometimes invalidates clang's current
working directory.
Reported by: decke
MFC 262809:
Pull in r203007 from upstream clang trunk:
Don't produce an alias between destructors with different calling conventions.
Fixes pr19007.
(Please note that is an LLVM PR identifier, not a FreeBSD one.)
This should fix Firefox and/or libxul crashes (due to problems with
regparm/stdcall calling conventions) on i386.
Reported by: multiple users on freebsd-current
PR: bin/187103
MFC 263048:
Repair recognition of "CC" as an alias for the C++ compiler, since it
was silently broken by upstream for a Windows-specific use-case.
Apparently some versions of CMake still rely on this archaic feature...
Reported by: rakuco
MFC 263049:
Garbage collect the old way of adding the libstdc++ include directories
in clang's InitHeaderSearch.cpp. This has been superseded by David
Chisnall's commit in r255321.
Moreover, if libc++ is used, the libstdc++ include directories should
not be in the search path at all. These directories are now only used
if you pass -stdlib=libstdc++.
Diffstat (limited to 'contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp | 577 |
1 files changed, 379 insertions, 198 deletions
diff --git a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp index 5ad8021..0621d7b 100644 --- a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp @@ -56,23 +56,36 @@ static const DeclContext *getEffectiveDeclContext(const Decl *D) { = dyn_cast_or_null<ParmVarDecl>(RD->getLambdaContextDecl())) return ContextParam->getDeclContext(); } + + // Perform the same check for block literals. + if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) { + if (ParmVarDecl *ContextParam + = dyn_cast_or_null<ParmVarDecl>(BD->getBlockManglingContextDecl())) + return ContextParam->getDeclContext(); + } - return D->getDeclContext(); + const DeclContext *DC = D->getDeclContext(); + if (const CapturedDecl *CD = dyn_cast<CapturedDecl>(DC)) + return getEffectiveDeclContext(CD); + + return DC; } static const DeclContext *getEffectiveParentContext(const DeclContext *DC) { return getEffectiveDeclContext(cast<Decl>(DC)); } - -static const CXXRecordDecl *GetLocalClassDecl(const NamedDecl *ND) { - const DeclContext *DC = dyn_cast<DeclContext>(ND); - if (!DC) - DC = getEffectiveDeclContext(ND); + +static bool isLocalContainerContext(const DeclContext *DC) { + return isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC) || isa<BlockDecl>(DC); +} + +static const RecordDecl *GetLocalClassDecl(const Decl *D) { + const DeclContext *DC = getEffectiveDeclContext(D); while (!DC->isNamespace() && !DC->isTranslationUnit()) { - const DeclContext *Parent = getEffectiveDeclContext(cast<Decl>(DC)); - if (isa<FunctionDecl>(Parent)) - return dyn_cast<CXXRecordDecl>(DC); - DC = Parent; + if (isLocalContainerContext(DC)) + return dyn_cast<RecordDecl>(D); + D = cast<Decl>(DC); + DC = getEffectiveDeclContext(D); } return 0; } @@ -91,15 +104,16 @@ static const NamedDecl *getStructor(const NamedDecl *decl) { static const unsigned UnknownArity = ~0U; -class ItaniumMangleContext : public MangleContext { +class ItaniumMangleContextImpl : public ItaniumMangleContext { llvm::DenseMap<const TagDecl *, uint64_t> AnonStructIds; - unsigned Discriminator; + typedef std::pair<const DeclContext*, IdentifierInfo*> DiscriminatorKeyTy; + llvm::DenseMap<DiscriminatorKeyTy, unsigned> Discriminator; llvm::DenseMap<const NamedDecl*, unsigned> Uniquifier; public: - explicit ItaniumMangleContext(ASTContext &Context, - DiagnosticsEngine &Diags) - : MangleContext(Context, Diags) { } + explicit ItaniumMangleContextImpl(ASTContext &Context, + DiagnosticsEngine &Diags) + : ItaniumMangleContext(Context, Diags) {} uint64_t getAnonymousStructId(const TagDecl *TD) { std::pair<llvm::DenseMap<const TagDecl *, @@ -108,16 +122,11 @@ public: return Result.first->second; } - void startNewFunction() { - MangleContext::startNewFunction(); - mangleInitDiscriminator(); - } - /// @name Mangler Entry Points /// @{ - bool shouldMangleDeclName(const NamedDecl *D); - void mangleName(const NamedDecl *D, raw_ostream &); + bool shouldMangleCXXName(const NamedDecl *D); + void mangleCXXName(const NamedDecl *D, raw_ostream &); void mangleThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk, raw_ostream &); @@ -135,30 +144,45 @@ public: raw_ostream &); void mangleCXXRTTI(QualType T, raw_ostream &); void mangleCXXRTTIName(QualType T, raw_ostream &); + void mangleTypeName(QualType T, raw_ostream &); void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type, raw_ostream &); void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type, raw_ostream &); - void mangleItaniumGuardVariable(const VarDecl *D, raw_ostream &); + void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &); + void mangleDynamicInitializer(const VarDecl *D, raw_ostream &Out); + void mangleDynamicAtExitDestructor(const VarDecl *D, raw_ostream &Out); void mangleItaniumThreadLocalInit(const VarDecl *D, raw_ostream &); void mangleItaniumThreadLocalWrapper(const VarDecl *D, raw_ostream &); - void mangleInitDiscriminator() { - Discriminator = 0; - } - bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) { - // Lambda closure types with external linkage (indicated by a - // non-zero lambda mangling number) have their own numbering scheme, so - // they do not need a discriminator. + // Lambda closure types are already numbered. if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(ND)) - if (RD->isLambda() && RD->getLambdaManglingNumber() > 0) + if (RD->isLambda()) return false; - + + // Anonymous tags are already numbered. + if (const TagDecl *Tag = dyn_cast<TagDecl>(ND)) { + if (Tag->getName().empty() && !Tag->getTypedefNameForAnonDecl()) + return false; + } + + // Use the canonical number for externally visible decls. + if (ND->isExternallyVisible()) { + unsigned discriminator = getASTContext().getManglingNumber(ND); + if (discriminator == 1) + return false; + disc = discriminator - 2; + return true; + } + + // Make up a reasonable number for internal decls. unsigned &discriminator = Uniquifier[ND]; - if (!discriminator) - discriminator = ++Discriminator; + if (!discriminator) { + const DeclContext *DC = getEffectiveDeclContext(ND); + discriminator = ++Discriminator[std::make_pair(DC, ND->getIdentifier())]; + } if (discriminator == 1) return false; disc = discriminator-2; @@ -169,7 +193,7 @@ public: /// CXXNameMangler - Manage the mangling of a single name. class CXXNameMangler { - ItaniumMangleContext &Context; + ItaniumMangleContextImpl &Context; raw_ostream &Out; /// The "structor" is the top-level declaration being mangled, if @@ -225,7 +249,7 @@ class CXXNameMangler { ASTContext &getASTContext() const { return Context.getASTContext(); } public: - CXXNameMangler(ItaniumMangleContext &C, raw_ostream &Out_, + CXXNameMangler(ItaniumMangleContextImpl &C, raw_ostream &Out_, const NamedDecl *D = 0) : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(0), SeqID(0) { @@ -233,11 +257,11 @@ public: assert(!D || (!isa<CXXDestructorDecl>(D) && !isa<CXXConstructorDecl>(D))); } - CXXNameMangler(ItaniumMangleContext &C, raw_ostream &Out_, + CXXNameMangler(ItaniumMangleContextImpl &C, raw_ostream &Out_, const CXXConstructorDecl *D, CXXCtorType Type) : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type), SeqID(0) { } - CXXNameMangler(ItaniumMangleContext &C, raw_ostream &Out_, + CXXNameMangler(ItaniumMangleContextImpl &C, raw_ostream &Out_, const CXXDestructorDecl *D, CXXDtorType Type) : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type), SeqID(0) { } @@ -305,7 +329,9 @@ private: void mangleUnscopedTemplateName(const TemplateDecl *ND); void mangleUnscopedTemplateName(TemplateName); void mangleSourceName(const IdentifierInfo *II); - void mangleLocalName(const NamedDecl *ND); + void mangleLocalName(const Decl *D); + void mangleBlockForPrefix(const BlockDecl *Block); + void mangleUnqualifiedBlock(const BlockDecl *Block); void mangleLambda(const CXXRecordDecl *Lambda); void mangleNestedName(const NamedDecl *ND, const DeclContext *DC, bool NoFunction=false); @@ -315,7 +341,7 @@ private: void manglePrefix(NestedNameSpecifier *qualifier); void manglePrefix(const DeclContext *DC, bool NoFunction=false); void manglePrefix(QualType type); - void mangleTemplatePrefix(const TemplateDecl *ND); + void mangleTemplatePrefix(const TemplateDecl *ND, bool NoFunction=false); void mangleTemplatePrefix(TemplateName Template); void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity); void mangleQualifiers(Qualifiers Quals); @@ -334,6 +360,7 @@ private: void mangleBareFunctionType(const FunctionType *T, bool MangleReturnType); void mangleNeonVectorType(const VectorType *T); + void mangleAArch64NeonVectorType(const VectorType *T); void mangleIntegerLiteral(QualType T, const llvm::APSInt &Value); void mangleMemberExpr(const Expr *base, bool isArrow, @@ -358,16 +385,7 @@ private: } -bool ItaniumMangleContext::shouldMangleDeclName(const NamedDecl *D) { - // In C, functions with no attributes never need to be mangled. Fastpath them. - if (!getASTContext().getLangOpts().CPlusPlus && !D->hasAttrs()) - return false; - - // Any decl can be declared with __asm("foo") on it, and this takes precedence - // over all other naming in the .o file. - if (D->hasAttr<AsmLabelAttr>()) - return true; - +bool ItaniumMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) { const FunctionDecl *FD = dyn_cast<FunctionDecl>(D); if (FD) { LanguageLinkage L = FD->getLanguageLinkage(); @@ -405,7 +423,8 @@ bool ItaniumMangleContext::shouldMangleDeclName(const NamedDecl *D) { if (DC->isFunctionOrMethod() && D->hasLinkage()) while (!DC->isNamespace() && !DC->isTranslationUnit()) DC = getEffectiveParentContext(DC); - if (DC->isTranslationUnit() && D->getLinkage() != InternalLinkage) + if (DC->isTranslationUnit() && D->getFormalLinkage() != InternalLinkage && + !isa<VarTemplateSpecializationDecl>(D)) return false; } @@ -413,26 +432,6 @@ bool ItaniumMangleContext::shouldMangleDeclName(const NamedDecl *D) { } void CXXNameMangler::mangle(const NamedDecl *D, StringRef Prefix) { - // Any decl can be declared with __asm("foo") on it, and this takes precedence - // over all other naming in the .o file. - if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) { - // If we have an asm name, then we use it as the mangling. - - // Adding the prefix can cause problems when one file has a "foo" and - // another has a "\01foo". That is known to happen on ELF with the - // tricks normally used for producing aliases (PR9177). Fortunately the - // llvm mangler on ELF is a nop, so we can just avoid adding the \01 - // marker. We also avoid adding the marker if this is an alias for an - // LLVM intrinsic. - StringRef UserLabelPrefix = - getASTContext().getTargetInfo().getUserLabelPrefix(); - if (!UserLabelPrefix.empty() && !ALA->getLabel().startswith("llvm.")) - Out << '\01'; // LLVM IR Marker for __asm("foo") - - Out << ALA->getLabel(); - return; - } - // <mangled-name> ::= _Z <encoding> // ::= <data name> // ::= <special-name> @@ -441,6 +440,8 @@ void CXXNameMangler::mangle(const NamedDecl *D, StringRef Prefix) { mangleFunctionEncoding(FD); else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) mangleName(VD); + else if (const IndirectFieldDecl *IFD = dyn_cast<IndirectFieldDecl>(D)) + mangleName(IFD->getAnonField()); else mangleName(cast<FieldDecl>(D)); } @@ -527,6 +528,13 @@ isTemplate(const NamedDecl *ND, const TemplateArgumentList *&TemplateArgs) { return Spec->getSpecializedTemplate(); } + // Check if we have a variable template. + if (const VarTemplateSpecializationDecl *Spec = + dyn_cast<VarTemplateSpecializationDecl>(ND)) { + TemplateArgs = &Spec->getTemplateArgs(); + return Spec->getSpecializedTemplate(); + } + return 0; } @@ -550,7 +558,7 @@ void CXXNameMangler::mangleName(const NamedDecl *ND) { // is that of the containing namespace, or the translation unit. // FIXME: This is a hack; extern variables declared locally should have // a proper semantic declaration context! - if (isa<FunctionDecl>(DC) && ND->hasLinkage() && !isLambda(ND)) + if (isLocalContainerContext(DC) && ND->hasLinkage() && !isLambda(ND)) while (!DC->isNamespace() && !DC->isTranslationUnit()) DC = getEffectiveParentContext(DC); else if (GetLocalClassDecl(ND)) { @@ -573,7 +581,7 @@ void CXXNameMangler::mangleName(const NamedDecl *ND) { return; } - if (isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC)) { + if (isLocalContainerContext(DC)) { mangleLocalName(ND); return; } @@ -825,6 +833,7 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier, switch (type->getTypeClass()) { case Type::Builtin: case Type::Complex: + case Type::Decayed: case Type::Pointer: case Type::BlockPointer: case Type::LValueReference: @@ -1053,7 +1062,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, // static void foo(); // This naming convention is the same as that followed by GCC, // though it shouldn't actually matter. - if (ND && ND->getLinkage() == InternalLinkage && + if (ND && ND->getFormalLinkage() == InternalLinkage && getEffectiveDeclContext(ND)->isFileContext()) Out << 'L'; @@ -1129,11 +1138,11 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, } } - int UnnamedMangle = Context.getASTContext().getUnnamedTagManglingNumber(TD); - if (UnnamedMangle != -1) { + if (TD->isExternallyVisible()) { + unsigned UnnamedMangle = getASTContext().getManglingNumber(TD); Out << "Ut"; - if (UnnamedMangle != 0) - Out << llvm::utostr(UnnamedMangle - 1); + if (UnnamedMangle > 1) + Out << llvm::utostr(UnnamedMangle - 2); Out << '_'; break; } @@ -1231,14 +1240,19 @@ void CXXNameMangler::mangleNestedName(const NamedDecl *ND, Out << 'N'; if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(ND)) { - mangleQualifiers(Qualifiers::fromCVRMask(Method->getTypeQualifiers())); + Qualifiers MethodQuals = + Qualifiers::fromCVRMask(Method->getTypeQualifiers()); + // We do not consider restrict a distinguishing attribute for overloading + // purposes so we must not mangle it. + MethodQuals.removeRestrict(); + mangleQualifiers(MethodQuals); mangleRefQualifier(Method->getRefQualifier()); } // Check if we have a template. const TemplateArgumentList *TemplateArgs = 0; if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) { - mangleTemplatePrefix(TD); + mangleTemplatePrefix(TD, NoFunction); mangleTemplateArgs(*TemplateArgs); } else { @@ -1261,36 +1275,37 @@ void CXXNameMangler::mangleNestedName(const TemplateDecl *TD, Out << 'E'; } -void CXXNameMangler::mangleLocalName(const NamedDecl *ND) { +void CXXNameMangler::mangleLocalName(const Decl *D) { // <local-name> := Z <function encoding> E <entity name> [<discriminator>] // := Z <function encoding> E s [<discriminator>] // <local-name> := Z <function encoding> E d [ <parameter number> ] // _ <entity name> // <discriminator> := _ <non-negative number> - const DeclContext *DC = getEffectiveDeclContext(ND); - if (isa<ObjCMethodDecl>(DC) && isa<FunctionDecl>(ND)) { - // Don't add objc method name mangling to locally declared function - mangleUnqualifiedName(ND); - return; - } + assert(isa<NamedDecl>(D) || isa<BlockDecl>(D)); + const RecordDecl *RD = GetLocalClassDecl(D); + const DeclContext *DC = getEffectiveDeclContext(RD ? RD : D); Out << 'Z'; - if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(DC)) { - mangleObjCMethodName(MD); - } else if (const CXXRecordDecl *RD = GetLocalClassDecl(ND)) { - mangleFunctionEncoding(cast<FunctionDecl>(getEffectiveDeclContext(RD))); - Out << 'E'; + if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(DC)) + mangleObjCMethodName(MD); + else if (const BlockDecl *BD = dyn_cast<BlockDecl>(DC)) + mangleBlockForPrefix(BD); + else + mangleFunctionEncoding(cast<FunctionDecl>(DC)); + + Out << 'E'; + if (RD) { // The parameter number is omitted for the last parameter, 0 for the // second-to-last parameter, 1 for the third-to-last parameter, etc. The // <entity name> will of course contain a <closure-type-name>: Its // numbering will be local to the particular argument in which it appears // -- other default arguments do not affect its encoding. - bool SkipDiscriminator = false; - if (RD->isLambda()) { + const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD); + if (CXXRD->isLambda()) { if (const ParmVarDecl *Parm - = dyn_cast_or_null<ParmVarDecl>(RD->getLambdaContextDecl())) { + = dyn_cast_or_null<ParmVarDecl>(CXXRD->getLambdaContextDecl())) { if (const FunctionDecl *Func = dyn_cast<FunctionDecl>(Parm->getDeclContext())) { Out << 'd'; @@ -1298,34 +1313,88 @@ void CXXNameMangler::mangleLocalName(const NamedDecl *ND) { if (Num > 1) mangleNumber(Num - 2); Out << '_'; - SkipDiscriminator = true; } } } // Mangle the name relative to the closest enclosing function. - if (ND == RD) // equality ok because RD derived from ND above - mangleUnqualifiedName(ND); - else - mangleNestedName(ND, DC, true /*NoFunction*/); - - if (!SkipDiscriminator) { - unsigned disc; - if (Context.getNextDiscriminator(RD, disc)) { - if (disc < 10) - Out << '_' << disc; - else - Out << "__" << disc << '_'; + // equality ok because RD derived from ND above + if (D == RD) { + mangleUnqualifiedName(RD); + } else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) { + manglePrefix(getEffectiveDeclContext(BD), true /*NoFunction*/); + mangleUnqualifiedBlock(BD); + } else { + const NamedDecl *ND = cast<NamedDecl>(D); + mangleNestedName(ND, getEffectiveDeclContext(ND), true /*NoFunction*/); + } + } else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) { + // Mangle a block in a default parameter; see above explanation for + // lambdas. + if (const ParmVarDecl *Parm + = dyn_cast_or_null<ParmVarDecl>(BD->getBlockManglingContextDecl())) { + if (const FunctionDecl *Func + = dyn_cast<FunctionDecl>(Parm->getDeclContext())) { + Out << 'd'; + unsigned Num = Func->getNumParams() - Parm->getFunctionScopeIndex(); + if (Num > 1) + mangleNumber(Num - 2); + Out << '_'; } } - + + mangleUnqualifiedBlock(BD); + } else { + mangleUnqualifiedName(cast<NamedDecl>(D)); + } + + if (const NamedDecl *ND = dyn_cast<NamedDecl>(RD ? RD : D)) { + unsigned disc; + if (Context.getNextDiscriminator(ND, disc)) { + if (disc < 10) + Out << '_' << disc; + else + Out << "__" << disc << '_'; + } + } +} + +void CXXNameMangler::mangleBlockForPrefix(const BlockDecl *Block) { + if (GetLocalClassDecl(Block)) { + mangleLocalName(Block); return; } - else - mangleFunctionEncoding(cast<FunctionDecl>(DC)); + const DeclContext *DC = getEffectiveDeclContext(Block); + if (isLocalContainerContext(DC)) { + mangleLocalName(Block); + return; + } + manglePrefix(getEffectiveDeclContext(Block)); + mangleUnqualifiedBlock(Block); +} - Out << 'E'; - mangleUnqualifiedName(ND); +void CXXNameMangler::mangleUnqualifiedBlock(const BlockDecl *Block) { + if (Decl *Context = Block->getBlockManglingContextDecl()) { + if ((isa<VarDecl>(Context) || isa<FieldDecl>(Context)) && + Context->getDeclContext()->isRecord()) { + if (const IdentifierInfo *Name + = cast<NamedDecl>(Context)->getIdentifier()) { + mangleSourceName(Name); + Out << 'M'; + } + } + } + + // If we have a block mangling number, use it. + unsigned Number = Block->getBlockManglingNumber(); + // Otherwise, just make up a number. It doesn't matter what it is because + // the symbol in question isn't externally visible. + if (!Number) + Number = Context.getBlockId(Block, false); + Out << "Ub"; + if (Number > 1) + Out << Number - 2; + Out << '_'; } void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) { @@ -1411,16 +1480,11 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) { if (DC->isTranslationUnit()) return; - if (const BlockDecl *Block = dyn_cast<BlockDecl>(DC)) { - manglePrefix(getEffectiveParentContext(DC), NoFunction); - SmallString<64> Name; - llvm::raw_svector_ostream NameStream(Name); - Context.mangleBlock(Block, NameStream); - NameStream.flush(); - Out << Name.size() << Name; + if (NoFunction && isLocalContainerContext(DC)) return; - } - + + assert(!isLocalContainerContext(DC)); + const NamedDecl *ND = cast<NamedDecl>(DC); if (mangleSubstitution(ND)) return; @@ -1430,12 +1494,7 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) { if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) { mangleTemplatePrefix(TD); mangleTemplateArgs(*TemplateArgs); - } - else if(NoFunction && (isa<FunctionDecl>(ND) || isa<ObjCMethodDecl>(ND))) - return; - else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) - mangleObjCMethodName(Method); - else { + } else { manglePrefix(getEffectiveDeclContext(ND), NoFunction); mangleUnqualifiedName(ND); } @@ -1466,7 +1525,8 @@ void CXXNameMangler::mangleTemplatePrefix(TemplateName Template) { mangleUnscopedTemplateName(Template); } -void CXXNameMangler::mangleTemplatePrefix(const TemplateDecl *ND) { +void CXXNameMangler::mangleTemplatePrefix(const TemplateDecl *ND, + bool NoFunction) { // <template-prefix> ::= <prefix> <template unqualified-name> // ::= <template-param> // ::= <substitution> @@ -1483,7 +1543,7 @@ void CXXNameMangler::mangleTemplatePrefix(const TemplateDecl *ND) { return; } - manglePrefix(getEffectiveDeclContext(ND)); + manglePrefix(getEffectiveDeclContext(ND), NoFunction); mangleUnqualifiedName(ND->getTemplatedDecl()); addSubstitution(ND); } @@ -1671,15 +1731,32 @@ void CXXNameMangler::mangleQualifiers(Qualifiers Quals) { Out << 'K'; if (Quals.hasAddressSpace()) { - // Extension: + // Address space extension: // - // <type> ::= U <address-space-number> - // - // where <address-space-number> is a source name consisting of 'AS' - // followed by the address space <number>. + // <type> ::= U <target-addrspace> + // <type> ::= U <OpenCL-addrspace> + // <type> ::= U <CUDA-addrspace> + SmallString<64> ASString; - ASString = "AS" + llvm::utostr_32( - Context.getASTContext().getTargetAddressSpace(Quals.getAddressSpace())); + unsigned AS = Quals.getAddressSpace(); + + if (Context.getASTContext().addressSpaceMapManglingFor(AS)) { + // <target-addrspace> ::= "AS" <address-space-number> + unsigned TargetAS = Context.getASTContext().getTargetAddressSpace(AS); + ASString = "AS" + llvm::utostr_32(TargetAS); + } else { + switch (AS) { + default: llvm_unreachable("Not a language specific address space"); + // <OpenCL-addrspace> ::= "CL" [ "global" | "local" | "constant" ] + case LangAS::opencl_global: ASString = "CLglobal"; break; + case LangAS::opencl_local: ASString = "CLlocal"; break; + case LangAS::opencl_constant: ASString = "CLconstant"; break; + // <CUDA-addrspace> ::= "CU" [ "device" | "constant" | "shared" ] + case LangAS::cuda_device: ASString = "CUdevice"; break; + case LangAS::cuda_constant: ASString = "CUconstant"; break; + case LangAS::cuda_shared: ASString = "CUshared"; break; + } + } Out << 'U' << ASString.size() << ASString; } @@ -1722,7 +1799,6 @@ void CXXNameMangler::mangleQualifiers(Qualifiers Quals) { void CXXNameMangler::mangleRefQualifier(RefQualifierKind RefQualifier) { // <ref-qualifier> ::= R # lvalue reference // ::= O # rvalue-reference - // Proposal to Itanium C++ ABI list on 1/26/11 switch (RefQualifier) { case RQ_None: break; @@ -1905,7 +1981,6 @@ void CXXNameMangler::mangleType(const BuiltinType *T) { // <type> ::= <function-type> // <function-type> ::= [<CV-qualifiers>] F [Y] // <bare-function-type> [<ref-qualifier>] E -// (Proposal to cxx-abi-dev, 2012-05-11) void CXXNameMangler::mangleType(const FunctionProtoType *T) { // Mangle CV-qualifiers, if present. These are 'this' qualifiers, // e.g. "const" in "int (A::*)() const". @@ -2101,7 +2176,9 @@ void CXXNameMangler::mangleNeonVectorType(const VectorType *T) { case BuiltinType::LongLong: EltName = "int64_t"; break; case BuiltinType::ULongLong: EltName = "uint64_t"; break; case BuiltinType::Float: EltName = "float32_t"; break; - default: llvm_unreachable("unexpected Neon vector element type"); + case BuiltinType::Half: EltName = "float16_t";break; + default: + llvm_unreachable("unexpected Neon vector element type"); } } const char *BaseName = 0; @@ -2117,6 +2194,71 @@ void CXXNameMangler::mangleNeonVectorType(const VectorType *T) { Out << BaseName << EltName; } +static StringRef mangleAArch64VectorBase(const BuiltinType *EltType) { + switch (EltType->getKind()) { + case BuiltinType::SChar: + return "Int8"; + case BuiltinType::Short: + return "Int16"; + case BuiltinType::Int: + return "Int32"; + case BuiltinType::LongLong: + return "Int64"; + case BuiltinType::UChar: + return "Uint8"; + case BuiltinType::UShort: + return "Uint16"; + case BuiltinType::UInt: + return "Uint32"; + case BuiltinType::ULongLong: + return "Uint64"; + case BuiltinType::Half: + return "Float16"; + case BuiltinType::Float: + return "Float32"; + case BuiltinType::Double: + return "Float64"; + default: + llvm_unreachable("Unexpected vector element base type"); + } +} + +// AArch64's ABI for Neon vector types specifies that they should be mangled as +// the equivalent internal name. The vector type must be one of the special +// types predefined by ARM. +void CXXNameMangler::mangleAArch64NeonVectorType(const VectorType *T) { + QualType EltType = T->getElementType(); + assert(EltType->isBuiltinType() && "Neon vector element not a BuiltinType"); + unsigned BitSize = + (T->getNumElements() * getASTContext().getTypeSize(EltType)); + (void)BitSize; // Silence warning. + + assert((BitSize == 64 || BitSize == 128) && + "Neon vector type not 64 or 128 bits"); + + StringRef EltName; + if (T->getVectorKind() == VectorType::NeonPolyVector) { + switch (cast<BuiltinType>(EltType)->getKind()) { + case BuiltinType::UChar: + EltName = "Poly8"; + break; + case BuiltinType::UShort: + EltName = "Poly16"; + break; + case BuiltinType::ULongLong: + EltName = "Poly64"; + break; + default: + llvm_unreachable("unexpected Neon polynomial vector element type"); + } + } else + EltName = mangleAArch64VectorBase(cast<BuiltinType>(EltType)); + + std::string TypeName = + ("__" + EltName + "x" + llvm::utostr(T->getNumElements()) + "_t").str(); + Out << TypeName.length() << TypeName; +} + // GNU extension: vector types // <type> ::= <vector-type> // <vector-type> ::= Dv <positive dimension number> _ @@ -2128,7 +2270,11 @@ void CXXNameMangler::mangleNeonVectorType(const VectorType *T) { void CXXNameMangler::mangleType(const VectorType *T) { if ((T->getVectorKind() == VectorType::NeonVector || T->getVectorKind() == VectorType::NeonPolyVector)) { - mangleNeonVectorType(T); + if (getASTContext().getTargetInfo().getTriple().getArch() == + llvm::Triple::aarch64) + mangleAArch64NeonVectorType(T); + else + mangleNeonVectorType(T); return; } Out << "Dv" << T->getNumElements() << '_'; @@ -2160,8 +2306,19 @@ void CXXNameMangler::mangleType(const ObjCInterfaceType *T) { } void CXXNameMangler::mangleType(const ObjCObjectType *T) { - // We don't allow overloading by different protocol qualification, - // so mangling them isn't necessary. + if (!T->qual_empty()) { + // Mangle protocol qualifiers. + SmallString<64> QualStr; + llvm::raw_svector_ostream QualOS(QualStr); + QualOS << "objcproto"; + ObjCObjectType::qual_iterator i = T->qual_begin(), e = T->qual_end(); + for ( ; i != e; ++i) { + StringRef name = (*i)->getName(); + QualOS << name.size() << name; + } + QualOS.flush(); + Out << 'U' << QualStr.size() << QualStr; + } mangleType(T->getBaseType()); } @@ -2422,6 +2579,7 @@ recurse: case Expr::OffsetOfExprClass: case Expr::PredefinedExprClass: case Expr::ShuffleVectorExprClass: + case Expr::ConvertVectorExprClass: case Expr::StmtExprClass: case Expr::UnaryTypeTraitExprClass: case Expr::BinaryTypeTraitExprClass: @@ -2477,6 +2635,10 @@ recurse: mangleExpression(cast<CXXDefaultInitExpr>(E)->getExpr(), Arity); break; + case Expr::CXXStdInitializerListExprClass: + mangleExpression(cast<CXXStdInitializerListExpr>(E)->getSubExpr(), Arity); + break; + case Expr::SubstNonTypeTemplateParmExprClass: mangleExpression(cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement(), Arity); @@ -2676,8 +2838,8 @@ recurse: case Expr::CXXThrowExprClass: { const CXXThrowExpr *TE = cast<CXXThrowExpr>(E); - - // Proposal from David Vandervoorde, 2010.06.30 + // <expression> ::= tw <expression> # throw expression + // ::= tr # rethrow if (TE->getSubExpr()) { Out << "tw"; mangleExpression(TE->getSubExpr()); @@ -2689,11 +2851,11 @@ recurse: case Expr::CXXTypeidExprClass: { const CXXTypeidExpr *TIE = cast<CXXTypeidExpr>(E); - - // Proposal from David Vandervoorde, 2010.06.30 + // <expression> ::= ti <type> # typeid (type) + // ::= te <expression> # typeid (expression) if (TIE->isTypeOperand()) { Out << "ti"; - mangleType(TIE->getTypeOperand()); + mangleType(TIE->getTypeOperand(Context.getASTContext())); } else { Out << "te"; mangleExpression(TIE->getExprOperand()); @@ -2703,8 +2865,8 @@ recurse: case Expr::CXXDeleteExprClass: { const CXXDeleteExpr *DE = cast<CXXDeleteExpr>(E); - - // Proposal from David Vandervoorde, 2010.06.30 + // <expression> ::= [gs] dl <expression> # [::] delete expr + // ::= [gs] da <expression> # [::] delete [] expr if (DE->isGlobalDelete()) Out << "gs"; Out << (DE->isArrayForm() ? "da" : "dl"); mangleExpression(DE->getArgument()); @@ -2935,8 +3097,6 @@ recurse: // fallthrough case Expr::CXXNullPtrLiteralExprClass: { - // Proposal from David Vandervoorde, 2010.06.30, as - // modified by ABI list discussion. Out << "LDnE"; break; } @@ -3101,7 +3261,6 @@ void CXXNameMangler::mangleTemplateArg(TemplateArgument A) { // ::= X <expression> E # expression // ::= <expr-primary> # simple expressions // ::= J <template-arg>* E # argument pack - // ::= sp <expression> # pack expansion of (C++0x) if (!A.isInstantiationDependent() || A.isDependent()) A = Context.getASTContext().getCanonicalTemplateArgument(A); @@ -3181,9 +3340,9 @@ void CXXNameMangler::mangleTemplateArg(TemplateArgument A) { break; } case TemplateArgument::Pack: { - // Note: proposal by Mike Herrick on 12/20/10 + // <template-arg> ::= J <template-arg>* E Out << 'J'; - for (TemplateArgument::pack_iterator PA = A.pack_begin(), + for (TemplateArgument::pack_iterator PA = A.pack_begin(), PAEnd = A.pack_end(); PA != PAEnd; ++PA) mangleTemplateArg(*PA); @@ -3452,8 +3611,8 @@ void CXXNameMangler::addSubstitution(uintptr_t Ptr) { /// and this routine will return false. In this case, the caller should just /// emit the identifier of the declaration (\c D->getIdentifier()) as its /// name. -void ItaniumMangleContext::mangleName(const NamedDecl *D, - raw_ostream &Out) { +void ItaniumMangleContextImpl::mangleCXXName(const NamedDecl *D, + raw_ostream &Out) { assert((isa<FunctionDecl>(D) || isa<VarDecl>(D)) && "Invalid mangleName() call, argument is not a variable or function!"); assert(!isa<CXXConstructorDecl>(D) && !isa<CXXDestructorDecl>(D) && @@ -3467,23 +3626,23 @@ void ItaniumMangleContext::mangleName(const NamedDecl *D, return Mangler.mangle(D); } -void ItaniumMangleContext::mangleCXXCtor(const CXXConstructorDecl *D, - CXXCtorType Type, - raw_ostream &Out) { +void ItaniumMangleContextImpl::mangleCXXCtor(const CXXConstructorDecl *D, + CXXCtorType Type, + raw_ostream &Out) { CXXNameMangler Mangler(*this, Out, D, Type); Mangler.mangle(D); } -void ItaniumMangleContext::mangleCXXDtor(const CXXDestructorDecl *D, - CXXDtorType Type, - raw_ostream &Out) { +void ItaniumMangleContextImpl::mangleCXXDtor(const CXXDestructorDecl *D, + CXXDtorType Type, + raw_ostream &Out) { CXXNameMangler Mangler(*this, Out, D, Type); Mangler.mangle(D); } -void ItaniumMangleContext::mangleThunk(const CXXMethodDecl *MD, - const ThunkInfo &Thunk, - raw_ostream &Out) { +void ItaniumMangleContextImpl::mangleThunk(const CXXMethodDecl *MD, + const ThunkInfo &Thunk, + raw_ostream &Out) { // <special-name> ::= T <call-offset> <base encoding> // # base is the nominal target function of thunk // <special-name> ::= Tc <call-offset> <call-offset> <base encoding> @@ -3499,21 +3658,20 @@ void ItaniumMangleContext::mangleThunk(const CXXMethodDecl *MD, Mangler.getStream() << 'c'; // Mangle the 'this' pointer adjustment. - Mangler.mangleCallOffset(Thunk.This.NonVirtual, Thunk.This.VCallOffsetOffset); - + Mangler.mangleCallOffset(Thunk.This.NonVirtual, + Thunk.This.Virtual.Itanium.VCallOffsetOffset); + // Mangle the return pointer adjustment if there is one. if (!Thunk.Return.isEmpty()) Mangler.mangleCallOffset(Thunk.Return.NonVirtual, - Thunk.Return.VBaseOffsetOffset); - + Thunk.Return.Virtual.Itanium.VBaseOffsetOffset); + Mangler.mangleFunctionEncoding(MD); } -void -ItaniumMangleContext::mangleCXXDtorThunk(const CXXDestructorDecl *DD, - CXXDtorType Type, - const ThisAdjustment &ThisAdjustment, - raw_ostream &Out) { +void ItaniumMangleContextImpl::mangleCXXDtorThunk( + const CXXDestructorDecl *DD, CXXDtorType Type, + const ThisAdjustment &ThisAdjustment, raw_ostream &Out) { // <special-name> ::= T <call-offset> <base encoding> // # base is the nominal target function of thunk CXXNameMangler Mangler(*this, Out, DD, Type); @@ -3521,15 +3679,15 @@ ItaniumMangleContext::mangleCXXDtorThunk(const CXXDestructorDecl *DD, // Mangle the 'this' pointer adjustment. Mangler.mangleCallOffset(ThisAdjustment.NonVirtual, - ThisAdjustment.VCallOffsetOffset); + ThisAdjustment.Virtual.Itanium.VCallOffsetOffset); Mangler.mangleFunctionEncoding(DD); } /// mangleGuardVariable - Returns the mangled name for a guard variable /// for the passed in VarDecl. -void ItaniumMangleContext::mangleItaniumGuardVariable(const VarDecl *D, - raw_ostream &Out) { +void ItaniumMangleContextImpl::mangleStaticGuardVariable(const VarDecl *D, + raw_ostream &Out) { // <special-name> ::= GV <object name> # Guard variable for one-time // # initialization CXXNameMangler Mangler(*this, Out); @@ -3537,24 +3695,44 @@ void ItaniumMangleContext::mangleItaniumGuardVariable(const VarDecl *D, Mangler.mangleName(D); } -void ItaniumMangleContext::mangleItaniumThreadLocalInit(const VarDecl *D, +void ItaniumMangleContextImpl::mangleDynamicInitializer(const VarDecl *MD, raw_ostream &Out) { + // These symbols are internal in the Itanium ABI, so the names don't matter. + // Clang has traditionally used this symbol and allowed LLVM to adjust it to + // avoid duplicate symbols. + Out << "__cxx_global_var_init"; +} + +void ItaniumMangleContextImpl::mangleDynamicAtExitDestructor(const VarDecl *D, + raw_ostream &Out) { + // Prefix the mangling of D with __dtor_. + CXXNameMangler Mangler(*this, Out); + Mangler.getStream() << "__dtor_"; + if (shouldMangleDeclName(D)) + Mangler.mangle(D); + else + Mangler.getStream() << D->getName(); +} + +void ItaniumMangleContextImpl::mangleItaniumThreadLocalInit(const VarDecl *D, + raw_ostream &Out) { // <special-name> ::= TH <object name> CXXNameMangler Mangler(*this, Out); Mangler.getStream() << "_ZTH"; Mangler.mangleName(D); } -void ItaniumMangleContext::mangleItaniumThreadLocalWrapper(const VarDecl *D, - raw_ostream &Out) { +void +ItaniumMangleContextImpl::mangleItaniumThreadLocalWrapper(const VarDecl *D, + raw_ostream &Out) { // <special-name> ::= TW <object name> CXXNameMangler Mangler(*this, Out); Mangler.getStream() << "_ZTW"; Mangler.mangleName(D); } -void ItaniumMangleContext::mangleReferenceTemporary(const VarDecl *D, - raw_ostream &Out) { +void ItaniumMangleContextImpl::mangleReferenceTemporary(const VarDecl *D, + raw_ostream &Out) { // We match the GCC mangling here. // <special-name> ::= GR <object name> CXXNameMangler Mangler(*this, Out); @@ -3562,26 +3740,26 @@ void ItaniumMangleContext::mangleReferenceTemporary(const VarDecl *D, Mangler.mangleName(D); } -void ItaniumMangleContext::mangleCXXVTable(const CXXRecordDecl *RD, - raw_ostream &Out) { +void ItaniumMangleContextImpl::mangleCXXVTable(const CXXRecordDecl *RD, + raw_ostream &Out) { // <special-name> ::= TV <type> # virtual table CXXNameMangler Mangler(*this, Out); Mangler.getStream() << "_ZTV"; Mangler.mangleNameOrStandardSubstitution(RD); } -void ItaniumMangleContext::mangleCXXVTT(const CXXRecordDecl *RD, - raw_ostream &Out) { +void ItaniumMangleContextImpl::mangleCXXVTT(const CXXRecordDecl *RD, + raw_ostream &Out) { // <special-name> ::= TT <type> # VTT structure CXXNameMangler Mangler(*this, Out); Mangler.getStream() << "_ZTT"; Mangler.mangleNameOrStandardSubstitution(RD); } -void ItaniumMangleContext::mangleCXXCtorVTable(const CXXRecordDecl *RD, - int64_t Offset, - const CXXRecordDecl *Type, - raw_ostream &Out) { +void ItaniumMangleContextImpl::mangleCXXCtorVTable(const CXXRecordDecl *RD, + int64_t Offset, + const CXXRecordDecl *Type, + raw_ostream &Out) { // <special-name> ::= TC <type> <offset number> _ <base type> CXXNameMangler Mangler(*this, Out); Mangler.getStream() << "_ZTC"; @@ -3591,8 +3769,7 @@ void ItaniumMangleContext::mangleCXXCtorVTable(const CXXRecordDecl *RD, Mangler.mangleNameOrStandardSubstitution(Type); } -void ItaniumMangleContext::mangleCXXRTTI(QualType Ty, - raw_ostream &Out) { +void ItaniumMangleContextImpl::mangleCXXRTTI(QualType Ty, raw_ostream &Out) { // <special-name> ::= TI <type> # typeinfo structure assert(!Ty.hasQualifiers() && "RTTI info cannot have top-level qualifiers"); CXXNameMangler Mangler(*this, Out); @@ -3600,15 +3777,19 @@ void ItaniumMangleContext::mangleCXXRTTI(QualType Ty, Mangler.mangleType(Ty); } -void ItaniumMangleContext::mangleCXXRTTIName(QualType Ty, - raw_ostream &Out) { +void ItaniumMangleContextImpl::mangleCXXRTTIName(QualType Ty, + raw_ostream &Out) { // <special-name> ::= TS <type> # typeinfo name (null terminated byte string) CXXNameMangler Mangler(*this, Out); Mangler.getStream() << "_ZTS"; Mangler.mangleType(Ty); } -MangleContext *clang::createItaniumMangleContext(ASTContext &Context, - DiagnosticsEngine &Diags) { - return new ItaniumMangleContext(Context, Diags); +void ItaniumMangleContextImpl::mangleTypeName(QualType Ty, raw_ostream &Out) { + mangleCXXRTTIName(Ty, Out); +} + +ItaniumMangleContext * +ItaniumMangleContext::create(ASTContext &Context, DiagnosticsEngine &Diags) { + return new ItaniumMangleContextImpl(Context, Diags); } |