Home | History | Annotate | Download | only in Index
      1 //===- CodegenNameGenerator.cpp - Codegen name generation -----------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // Determines the name that the symbol will get for code generation.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "clang/Index/CodegenNameGenerator.h"
     15 #include "clang/AST/ASTContext.h"
     16 #include "clang/AST/DeclCXX.h"
     17 #include "clang/AST/DeclObjC.h"
     18 #include "clang/AST/Mangle.h"
     19 #include "clang/AST/VTableBuilder.h"
     20 #include "clang/Basic/TargetInfo.h"
     21 #include "llvm/IR/DataLayout.h"
     22 #include "llvm/IR/Mangler.h"
     23 #include "llvm/Support/raw_ostream.h"
     24 
     25 using namespace clang;
     26 using namespace clang::index;
     27 
     28 struct CodegenNameGenerator::Implementation {
     29   std::unique_ptr<MangleContext> MC;
     30   llvm::DataLayout DL;
     31 
     32   Implementation(ASTContext &Ctx)
     33     : MC(Ctx.createMangleContext()),
     34       DL(Ctx.getTargetInfo().getDataLayout()) {}
     35 
     36   bool writeName(const Decl *D, raw_ostream &OS) {
     37     // First apply frontend mangling.
     38     SmallString<128> FrontendBuf;
     39     llvm::raw_svector_ostream FrontendBufOS(FrontendBuf);
     40     if (auto *FD = dyn_cast<FunctionDecl>(D)) {
     41       if (FD->isDependentContext())
     42         return true;
     43       if (writeFuncOrVarName(FD, FrontendBufOS))
     44         return true;
     45     } else if (auto *VD = dyn_cast<VarDecl>(D)) {
     46       if (writeFuncOrVarName(VD, FrontendBufOS))
     47         return true;
     48     } else if (auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
     49       MC->mangleObjCMethodNameWithoutSize(MD, OS);
     50       return false;
     51     } else if (auto *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
     52       writeObjCClassName(ID, FrontendBufOS);
     53     } else {
     54       return true;
     55     }
     56 
     57     // Now apply backend mangling.
     58     llvm::Mangler::getNameWithPrefix(OS, FrontendBufOS.str(), DL);
     59     return false;
     60   }
     61 
     62   std::string getName(const Decl *D) {
     63     std::string Name;
     64     {
     65       llvm::raw_string_ostream OS(Name);
     66       writeName(D, OS);
     67     }
     68     return Name;
     69   }
     70 
     71   std::vector<std::string> getAllManglings(const Decl *D) {
     72     if (!(isa<CXXRecordDecl>(D) || isa<CXXMethodDecl>(D)))
     73       return {};
     74 
     75     const NamedDecl *ND = cast<NamedDecl>(D);
     76 
     77     ASTContext &Ctx = ND->getASTContext();
     78     std::unique_ptr<MangleContext> M(Ctx.createMangleContext());
     79 
     80     std::vector<std::string> Manglings;
     81 
     82     auto hasDefaultCXXMethodCC = [](ASTContext &C, const CXXMethodDecl *MD) {
     83       auto DefaultCC = C.getDefaultCallingConvention(/*IsVariadic=*/false,
     84                                                      /*IsCSSMethod=*/true);
     85       auto CC = MD->getType()->getAs<FunctionProtoType>()->getCallConv();
     86       return CC == DefaultCC;
     87     };
     88 
     89     if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(ND)) {
     90       Manglings.emplace_back(getMangledStructor(CD, Ctor_Base));
     91 
     92       if (Ctx.getTargetInfo().getCXXABI().isItaniumFamily())
     93         if (!CD->getParent()->isAbstract())
     94           Manglings.emplace_back(getMangledStructor(CD, Ctor_Complete));
     95 
     96       if (Ctx.getTargetInfo().getCXXABI().isMicrosoft())
     97         if (CD->hasAttr<DLLExportAttr>() && CD->isDefaultConstructor())
     98           if (!(hasDefaultCXXMethodCC(Ctx, CD) && CD->getNumParams() == 0))
     99             Manglings.emplace_back(getMangledStructor(CD, Ctor_DefaultClosure));
    100     } else if (const auto *DD = dyn_cast_or_null<CXXDestructorDecl>(ND)) {
    101       Manglings.emplace_back(getMangledStructor(DD, Dtor_Base));
    102       if (Ctx.getTargetInfo().getCXXABI().isItaniumFamily()) {
    103         Manglings.emplace_back(getMangledStructor(DD, Dtor_Complete));
    104         if (DD->isVirtual())
    105           Manglings.emplace_back(getMangledStructor(DD, Dtor_Deleting));
    106       }
    107     } else if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(ND)) {
    108       Manglings.emplace_back(getName(ND));
    109       if (MD->isVirtual())
    110         if (const auto *TIV = Ctx.getVTableContext()->getThunkInfo(MD))
    111           for (const auto &T : *TIV)
    112             Manglings.emplace_back(getMangledThunk(MD, T));
    113     }
    114 
    115     return Manglings;
    116   }
    117 
    118 private:
    119   bool writeFuncOrVarName(const NamedDecl *D, raw_ostream &OS) {
    120     if (MC->shouldMangleDeclName(D)) {
    121       if (const auto *CtorD = dyn_cast<CXXConstructorDecl>(D))
    122         MC->mangleCXXCtor(CtorD, Ctor_Complete, OS);
    123       else if (const auto *DtorD = dyn_cast<CXXDestructorDecl>(D))
    124         MC->mangleCXXDtor(DtorD, Dtor_Complete, OS);
    125       else
    126         MC->mangleName(D, OS);
    127       return false;
    128     } else {
    129       IdentifierInfo *II = D->getIdentifier();
    130       if (!II)
    131         return true;
    132       OS << II->getName();
    133       return false;
    134     }
    135   }
    136 
    137   void writeObjCClassName(const ObjCInterfaceDecl *D, raw_ostream &OS) {
    138     OS << getClassSymbolPrefix();
    139     OS << D->getObjCRuntimeNameAsString();
    140   }
    141 
    142   static StringRef getClassSymbolPrefix() {
    143     return "OBJC_CLASS_$_";
    144   }
    145 
    146   std::string getMangledStructor(const NamedDecl *ND, unsigned StructorType) {
    147     std::string FrontendBuf;
    148     llvm::raw_string_ostream FOS(FrontendBuf);
    149 
    150     if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(ND))
    151       MC->mangleCXXCtor(CD, static_cast<CXXCtorType>(StructorType), FOS);
    152     else if (const auto *DD = dyn_cast_or_null<CXXDestructorDecl>(ND))
    153       MC->mangleCXXDtor(DD, static_cast<CXXDtorType>(StructorType), FOS);
    154 
    155     std::string BackendBuf;
    156     llvm::raw_string_ostream BOS(BackendBuf);
    157 
    158     llvm::Mangler::getNameWithPrefix(BOS, FOS.str(), DL);
    159 
    160     return BOS.str();
    161   }
    162 
    163   std::string getMangledThunk(const CXXMethodDecl *MD, const ThunkInfo &T) {
    164     std::string FrontendBuf;
    165     llvm::raw_string_ostream FOS(FrontendBuf);
    166 
    167     MC->mangleThunk(MD, T, FOS);
    168 
    169     std::string BackendBuf;
    170     llvm::raw_string_ostream BOS(BackendBuf);
    171 
    172     llvm::Mangler::getNameWithPrefix(BOS, FOS.str(), DL);
    173 
    174     return BOS.str();
    175   }
    176 };
    177 
    178 CodegenNameGenerator::CodegenNameGenerator(ASTContext &Ctx)
    179   : Impl(new Implementation(Ctx)) {
    180 }
    181 
    182 CodegenNameGenerator::~CodegenNameGenerator() {
    183 }
    184 
    185 bool CodegenNameGenerator::writeName(const Decl *D, raw_ostream &OS) {
    186   return Impl->writeName(D, OS);
    187 }
    188 
    189 std::string CodegenNameGenerator::getName(const Decl *D) {
    190   return Impl->getName(D);
    191 }
    192 
    193 std::vector<std::string> CodegenNameGenerator::getAllManglings(const Decl *D) {
    194   return Impl->getAllManglings(D);
    195 }
    196