From: Mike Stump Date: Wed, 2 Sep 2009 00:25:38 +0000 (+0000) Subject: Add mangling for thunks. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=141c5afc2bbb550b83f18e0284585b5ae477ad2a;p=clang Add mangling for thunks. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@80743 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp index 71b84e7001..c5014d3ff7 100644 --- a/lib/CodeGen/Mangle.cpp +++ b/lib/CodeGen/Mangle.cpp @@ -39,6 +39,8 @@ namespace { : Context(C), Out(os), Structor(0), StructorType(0) { } bool mangle(const NamedDecl *D); + void mangleThunkName(const NamedDecl *ND, bool Virtual, int64_t nv, + int64_t v); void mangleGuardVariable(const VarDecl *D); void mangleCXXVtable(QualType Type); @@ -87,8 +89,8 @@ static bool isInCLinkageSpecification(const Decl *D) { } bool CXXNameMangler::mangleFunctionDecl(const FunctionDecl *FD) { - // Clang's "overloadable" attribute extension to C/C++ implies - // name mangling (always). + // Clang's "overloadable" attribute extension to C/C++ implies name mangling + // (always). if (!FD->hasAttr()) { // C functions are not mangled, and "main" is never mangled. if (!Context.getLangOptions().CPlusPlus || FD->isMain(Context)) @@ -111,8 +113,8 @@ bool CXXNameMangler::mangleFunctionDecl(const FunctionDecl *FD) { } bool CXXNameMangler::mangle(const NamedDecl *D) { - // Any decl can be declared with __asm("foo") on it, and this takes - // precedence over all other naming in the .o file. + // 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()) { // If we have an asm name, then we use it as the mangling. Out << '\01'; // LLVM IR Marker for __asm("foo") @@ -185,9 +187,9 @@ void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) { // ::= mangleName(FD); - // Whether the mangling of a function type includes the return type depends - // on the context and the nature of the function. The rules for deciding - // whether the return type is included are: + // Whether the mangling of a function type includes the return type depends on + // the context and the nature of the function. The rules for deciding whether + // the return type is included are: // // 1. Template functions (names or types) have return types encoded, with // the exceptions listed below. @@ -196,8 +198,8 @@ void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) { // exceptions listed below. // 3. Non-template function names do not have return types encoded. // - // The exceptions mentioned in (1) and (2) above, for which the return - // type is never included, are + // The exceptions mentioned in (1) and (2) above, for which the return type is + // never included, are // 1. Constructors. // 2. Destructors. // 3. Conversion operator functions, e.g. operator int. @@ -236,6 +238,40 @@ void CXXNameMangler::mangleName(const NamedDecl *ND) { mangleNestedName(ND); } +void CXXNameMangler::mangleThunkName(const NamedDecl *D, bool Virtual, + int64_t nv, int64_t v) { + // ::= T + // # base is the nominal target function of thunk + // ::= h _ + // ::= v _ + // ::= # non-virtual base override + // ::= _ + // # virtual base override, with vcall offset + if (!Virtual) { + Out << "_Th"; + if (nv < 0) { + Out << "n"; + nv = -nv; + } + Out << nv; + } else { + Out << "_Tv"; + if (nv < 0) { + Out << "n"; + nv = -nv; + } + Out << nv; + Out << "_"; + if (v < 0) { + Out << "n"; + v = -v; + } + Out << v; + } + Out << "_"; + mangleName(D); +} + void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND) { // ::= // ::= @@ -254,8 +290,8 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND) { case DeclarationName::CXXConstructorName: if (ND == Structor) - // If the named decl is the C++ constructor we're mangling, use the - // type we were given. + // If the named decl is the C++ constructor we're mangling, use the type + // we were given. mangleCXXCtorType(static_cast(StructorType)); else // Otherwise, use the complete constructor name. This is relevant if a @@ -265,8 +301,8 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND) { case DeclarationName::CXXDestructorName: if (ND == Structor) - // If the named decl is the C++ destructor we're mangling, use the - // type we were given. + // If the named decl is the C++ destructor we're mangling, use the type we + // were given. mangleCXXDtorType(static_cast(StructorType)); else // Otherwise, use the complete destructor name. This is relevant if a @@ -637,8 +673,7 @@ void CXXNameMangler::mangleType(const TagType *T) { else mangleName(T->getDecl()); - // If this is a class template specialization, mangle the template - // arguments. + // If this is a class template specialization, mangle the template arguments. if (ClassTemplateSpecializationDecl *Spec = dyn_cast(T->getDecl())) mangleTemplateArgumentList(Spec->getTemplateArgs()); @@ -773,14 +808,14 @@ void CXXNameMangler::mangleTemplateArgument(const TemplateArgument &A) { } namespace clang { - /// \brief Mangles the name of the declaration D and emits that name - /// to the given output stream. + /// \brief Mangles the name of the declaration D and emits that name to the + /// given output stream. /// - /// If the declaration D requires a mangled name, this routine will - /// emit that mangled name to \p os and return true. Otherwise, \p - /// os will be unchanged 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. + /// If the declaration D requires a mangled name, this routine will emit that + /// mangled name to \p os and return true. Otherwise, \p os will be unchanged + /// 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. bool mangleName(const NamedDecl *D, ASTContext &Context, llvm::raw_ostream &os) { assert(!isa(D) && @@ -796,6 +831,21 @@ namespace clang { return true; } + /// \brief Mangles the a thunk with the offset n for the declaration D and + /// emits that name to the given output stream. + void mangleThunkName(const NamedDecl *D, bool Virtual, int64_t nv, + int64_t v, ASTContext &Context, llvm::raw_ostream &os) { + // FIXME: Hum, we might have to thunk these, fix. + assert(!isa(D) && + "Use mangleCXXCtor for constructor decls!"); + assert(!isa(D) && + "Use mangleCXXDtor for destructor decls!"); + + CXXNameMangler Mangler(Context, os); + Mangler.mangleThunkName(D, Virtual, nv, v); + os.flush(); + } + /// mangleGuardVariable - Returns the mangled name for a guard variable /// for the passed in VarDecl. void mangleGuardVariable(const VarDecl *D, ASTContext &Context, diff --git a/lib/CodeGen/Mangle.h b/lib/CodeGen/Mangle.h index 8f0a32da88..a2fba4e669 100644 --- a/lib/CodeGen/Mangle.h +++ b/lib/CodeGen/Mangle.h @@ -34,6 +34,8 @@ namespace clang { bool mangleName(const NamedDecl *D, ASTContext &Context, llvm::raw_ostream &os); + void mangleThunkName(const NamedDecl *D, bool Virtual, int64_t n, + int64_t vn, ASTContext &Context, llvm::raw_ostream &os); void mangleGuardVariable(const VarDecl *D, ASTContext &Context, llvm::raw_ostream &os); void mangleCXXVtable(QualType T, ASTContext &Context, llvm::raw_ostream &os);