14967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar//===- CodegenNameGenerator.cpp - Codegen name generation -----------------===//
24967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar//
34967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar//                     The LLVM Compiler Infrastructure
44967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar//
54967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar// This file is distributed under the University of Illinois Open Source
64967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar// License. See LICENSE.TXT for details.
74967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar//
84967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar//===----------------------------------------------------------------------===//
94967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar//
104967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar// Determines the name that the symbol will get for code generation.
114967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar//
124967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar//===----------------------------------------------------------------------===//
134967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
144967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar#include "clang/Index/CodegenNameGenerator.h"
154967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar#include "clang/AST/ASTContext.h"
164967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar#include "clang/AST/DeclCXX.h"
174967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar#include "clang/AST/DeclObjC.h"
184967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar#include "clang/AST/Mangle.h"
194967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar#include "clang/AST/VTableBuilder.h"
204967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar#include "clang/Basic/TargetInfo.h"
214967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar#include "llvm/IR/DataLayout.h"
224967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar#include "llvm/IR/Mangler.h"
234967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar#include "llvm/Support/raw_ostream.h"
244967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
254967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarusing namespace clang;
264967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarusing namespace clang::index;
274967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
284967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarstruct CodegenNameGenerator::Implementation {
294967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  std::unique_ptr<MangleContext> MC;
304967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  llvm::DataLayout DL;
314967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
324967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  Implementation(ASTContext &Ctx)
334967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    : MC(Ctx.createMangleContext()),
344967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      DL(Ctx.getTargetInfo().getDataLayout()) {}
354967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
364967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  bool writeName(const Decl *D, raw_ostream &OS) {
374967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    // First apply frontend mangling.
384967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    SmallString<128> FrontendBuf;
394967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    llvm::raw_svector_ostream FrontendBufOS(FrontendBuf);
404967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    if (auto *FD = dyn_cast<FunctionDecl>(D)) {
414967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      if (FD->isDependentContext())
424967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar        return true;
434967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      if (writeFuncOrVarName(FD, FrontendBufOS))
444967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar        return true;
454967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    } else if (auto *VD = dyn_cast<VarDecl>(D)) {
464967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      if (writeFuncOrVarName(VD, FrontendBufOS))
474967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar        return true;
484967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    } else if (auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
494967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      MC->mangleObjCMethodNameWithoutSize(MD, OS);
504967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      return false;
514967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    } else if (auto *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
524967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      writeObjCClassName(ID, FrontendBufOS);
534967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    } else {
544967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      return true;
554967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    }
564967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
574967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    // Now apply backend mangling.
584967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    llvm::Mangler::getNameWithPrefix(OS, FrontendBufOS.str(), DL);
594967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    return false;
604967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  }
614967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
624967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  std::string getName(const Decl *D) {
634967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    std::string Name;
644967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    {
654967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      llvm::raw_string_ostream OS(Name);
664967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      writeName(D, OS);
674967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    }
684967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    return Name;
694967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  }
704967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
714967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  std::vector<std::string> getAllManglings(const Decl *D) {
724967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    if (!(isa<CXXRecordDecl>(D) || isa<CXXMethodDecl>(D)))
734967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      return {};
744967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
754967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    const NamedDecl *ND = cast<NamedDecl>(D);
764967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
774967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    ASTContext &Ctx = ND->getASTContext();
784967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    std::unique_ptr<MangleContext> M(Ctx.createMangleContext());
794967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
804967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    std::vector<std::string> Manglings;
814967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
824967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    auto hasDefaultCXXMethodCC = [](ASTContext &C, const CXXMethodDecl *MD) {
834967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      auto DefaultCC = C.getDefaultCallingConvention(/*IsVariadic=*/false,
844967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar                                                     /*IsCSSMethod=*/true);
854967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      auto CC = MD->getType()->getAs<FunctionProtoType>()->getCallConv();
864967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      return CC == DefaultCC;
874967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    };
884967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
894967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(ND)) {
904967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      Manglings.emplace_back(getMangledStructor(CD, Ctor_Base));
914967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
924967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      if (Ctx.getTargetInfo().getCXXABI().isItaniumFamily())
934967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar        if (!CD->getParent()->isAbstract())
944967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar          Manglings.emplace_back(getMangledStructor(CD, Ctor_Complete));
954967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
964967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      if (Ctx.getTargetInfo().getCXXABI().isMicrosoft())
974967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar        if (CD->hasAttr<DLLExportAttr>() && CD->isDefaultConstructor())
984967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar          if (!(hasDefaultCXXMethodCC(Ctx, CD) && CD->getNumParams() == 0))
994967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar            Manglings.emplace_back(getMangledStructor(CD, Ctor_DefaultClosure));
1004967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    } else if (const auto *DD = dyn_cast_or_null<CXXDestructorDecl>(ND)) {
1014967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      Manglings.emplace_back(getMangledStructor(DD, Dtor_Base));
1024967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      if (Ctx.getTargetInfo().getCXXABI().isItaniumFamily()) {
1034967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar        Manglings.emplace_back(getMangledStructor(DD, Dtor_Complete));
1044967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar        if (DD->isVirtual())
1054967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar          Manglings.emplace_back(getMangledStructor(DD, Dtor_Deleting));
1064967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      }
1074967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    } else if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(ND)) {
1084967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      Manglings.emplace_back(getName(ND));
1094967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      if (MD->isVirtual())
1104967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar        if (const auto *TIV = Ctx.getVTableContext()->getThunkInfo(MD))
1114967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar          for (const auto &T : *TIV)
1124967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar            Manglings.emplace_back(getMangledThunk(MD, T));
1134967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    }
1144967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
1154967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    return Manglings;
1164967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  }
1174967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
1184967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarprivate:
1194967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  bool writeFuncOrVarName(const NamedDecl *D, raw_ostream &OS) {
1204967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    if (MC->shouldMangleDeclName(D)) {
1214967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      if (const auto *CtorD = dyn_cast<CXXConstructorDecl>(D))
1224967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar        MC->mangleCXXCtor(CtorD, Ctor_Complete, OS);
1234967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      else if (const auto *DtorD = dyn_cast<CXXDestructorDecl>(D))
1244967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar        MC->mangleCXXDtor(DtorD, Dtor_Complete, OS);
1254967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      else
1264967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar        MC->mangleName(D, OS);
1274967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      return false;
1284967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    } else {
1294967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      IdentifierInfo *II = D->getIdentifier();
1304967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      if (!II)
1314967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar        return true;
1324967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      OS << II->getName();
1334967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      return false;
1344967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    }
1354967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  }
1364967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
1374967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  void writeObjCClassName(const ObjCInterfaceDecl *D, raw_ostream &OS) {
1384967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    OS << getClassSymbolPrefix();
1394967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    OS << D->getObjCRuntimeNameAsString();
1404967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  }
1414967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
1424967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  static StringRef getClassSymbolPrefix() {
1434967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    return "OBJC_CLASS_$_";
1444967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  }
1454967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
1464967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  std::string getMangledStructor(const NamedDecl *ND, unsigned StructorType) {
1474967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    std::string FrontendBuf;
1484967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    llvm::raw_string_ostream FOS(FrontendBuf);
1494967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
1504967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(ND))
1514967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      MC->mangleCXXCtor(CD, static_cast<CXXCtorType>(StructorType), FOS);
1524967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    else if (const auto *DD = dyn_cast_or_null<CXXDestructorDecl>(ND))
1534967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      MC->mangleCXXDtor(DD, static_cast<CXXDtorType>(StructorType), FOS);
1544967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
1554967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    std::string BackendBuf;
1564967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    llvm::raw_string_ostream BOS(BackendBuf);
1574967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
1584967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    llvm::Mangler::getNameWithPrefix(BOS, FOS.str(), DL);
1594967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
1604967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    return BOS.str();
1614967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  }
1624967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
1634967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  std::string getMangledThunk(const CXXMethodDecl *MD, const ThunkInfo &T) {
1644967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    std::string FrontendBuf;
1654967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    llvm::raw_string_ostream FOS(FrontendBuf);
1664967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
1674967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    MC->mangleThunk(MD, T, FOS);
1684967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
1694967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    std::string BackendBuf;
1704967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    llvm::raw_string_ostream BOS(BackendBuf);
1714967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
1724967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    llvm::Mangler::getNameWithPrefix(BOS, FOS.str(), DL);
1734967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
1744967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar    return BOS.str();
1754967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  }
1764967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar};
1774967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
1784967a710c84587c654b56c828382219c3937dacbPirama Arumuga NainarCodegenNameGenerator::CodegenNameGenerator(ASTContext &Ctx)
1794967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  : Impl(new Implementation(Ctx)) {
1804967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar}
1814967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
1824967a710c84587c654b56c828382219c3937dacbPirama Arumuga NainarCodegenNameGenerator::~CodegenNameGenerator() {
1834967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar}
1844967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
1854967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarbool CodegenNameGenerator::writeName(const Decl *D, raw_ostream &OS) {
1864967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  return Impl->writeName(D, OS);
1874967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar}
1884967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
1894967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarstd::string CodegenNameGenerator::getName(const Decl *D) {
1904967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  return Impl->getName(D);
1914967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar}
1924967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar
1934967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarstd::vector<std::string> CodegenNameGenerator::getAllManglings(const Decl *D) {
1944967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar  return Impl->getAllManglings(D);
1954967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar}
196