brintos

brintos / llvm-project-archived public Read only

0
0
Text · 14.0 KiB · 8ec8aef Raw
410 lines · cpp
1//===--- ModuleBuilder.cpp - Emit LLVM Code from ASTs ---------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This builds an AST and converts it to LLVM Code.10//11//===----------------------------------------------------------------------===//12 13#include "clang/CodeGen/ModuleBuilder.h"14#include "CGDebugInfo.h"15#include "CodeGenModule.h"16#include "clang/AST/ASTContext.h"17#include "clang/AST/DeclObjC.h"18#include "clang/AST/Expr.h"19#include "clang/Basic/CodeGenOptions.h"20#include "clang/Basic/Diagnostic.h"21#include "clang/Basic/TargetInfo.h"22#include "llvm/ADT/StringRef.h"23#include "llvm/IR/DataLayout.h"24#include "llvm/IR/LLVMContext.h"25#include "llvm/IR/Module.h"26#include "llvm/Support/FormatVariadic.h"27#include "llvm/Support/VirtualFileSystem.h"28#include <memory>29 30using namespace clang;31using namespace CodeGen;32 33namespace {34  class CodeGeneratorImpl : public CodeGenerator {35    DiagnosticsEngine &Diags;36    ASTContext *Ctx;37    IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS; // Only used for debug info.38    const HeaderSearchOptions &HeaderSearchOpts; // Only used for debug info.39    const PreprocessorOptions &PreprocessorOpts; // Only used for debug info.40    const CodeGenOptions &CodeGenOpts;41 42    unsigned HandlingTopLevelDecls;43 44    /// Use this when emitting decls to block re-entrant decl emission. It will45    /// emit all deferred decls on scope exit. Set EmitDeferred to false if decl46    /// emission must be deferred longer, like at the end of a tag definition.47    struct HandlingTopLevelDeclRAII {48      CodeGeneratorImpl &Self;49      bool EmitDeferred;50      HandlingTopLevelDeclRAII(CodeGeneratorImpl &Self,51                               bool EmitDeferred = true)52          : Self(Self), EmitDeferred(EmitDeferred) {53        ++Self.HandlingTopLevelDecls;54      }55      ~HandlingTopLevelDeclRAII() {56        unsigned Level = --Self.HandlingTopLevelDecls;57        if (Level == 0 && EmitDeferred)58          Self.EmitDeferredDecls();59      }60    };61 62    CoverageSourceInfo *CoverageInfo;63 64  protected:65    std::unique_ptr<llvm::Module> M;66    std::unique_ptr<CodeGen::CodeGenModule> Builder;67 68  private:69    SmallVector<FunctionDecl *, 8> DeferredInlineMemberFuncDefs;70 71    static llvm::StringRef ExpandModuleName(llvm::StringRef ModuleName,72                                            const CodeGenOptions &CGO) {73      if (ModuleName == "-" && !CGO.MainFileName.empty())74        return CGO.MainFileName;75      return ModuleName;76    }77 78  public:79    CodeGeneratorImpl(DiagnosticsEngine &diags, llvm::StringRef ModuleName,80                      IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,81                      const HeaderSearchOptions &HSO,82                      const PreprocessorOptions &PPO, const CodeGenOptions &CGO,83                      llvm::LLVMContext &C,84                      CoverageSourceInfo *CoverageInfo = nullptr)85        : Diags(diags), Ctx(nullptr), FS(std::move(FS)), HeaderSearchOpts(HSO),86          PreprocessorOpts(PPO), CodeGenOpts(CGO), HandlingTopLevelDecls(0),87          CoverageInfo(CoverageInfo),88          M(new llvm::Module(ExpandModuleName(ModuleName, CGO), C)) {89      C.setDiscardValueNames(CGO.DiscardValueNames);90    }91 92    ~CodeGeneratorImpl() override {93      // There should normally not be any leftover inline method definitions.94      assert(DeferredInlineMemberFuncDefs.empty() ||95             Diags.hasErrorOccurred());96    }97 98    CodeGenModule &CGM() {99      return *Builder;100    }101 102    llvm::Module *GetModule() {103      return M.get();104    }105 106    CGDebugInfo *getCGDebugInfo() {107      return Builder->getModuleDebugInfo();108    }109 110    llvm::Module *ReleaseModule() {111      return M.release();112    }113 114    const Decl *GetDeclForMangledName(StringRef MangledName) {115      GlobalDecl Result;116      if (!Builder->lookupRepresentativeDecl(MangledName, Result))117        return nullptr;118      const Decl *D = Result.getCanonicalDecl().getDecl();119      if (auto FD = dyn_cast<FunctionDecl>(D)) {120        if (FD->hasBody(FD))121          return FD;122      } else if (auto TD = dyn_cast<TagDecl>(D)) {123        if (auto Def = TD->getDefinition())124          return Def;125      }126      return D;127    }128 129    llvm::StringRef GetMangledName(GlobalDecl GD) {130      return Builder->getMangledName(GD);131    }132 133    llvm::Constant *GetAddrOfGlobal(GlobalDecl global, bool isForDefinition) {134      return Builder->GetAddrOfGlobal(global, ForDefinition_t(isForDefinition));135    }136 137    llvm::Module *StartModule(llvm::StringRef ModuleName,138                              llvm::LLVMContext &C) {139      assert(!M && "Replacing existing Module?");140      M.reset(new llvm::Module(ExpandModuleName(ModuleName, CodeGenOpts), C));141 142      IRGenFinished = false;143 144      std::unique_ptr<CodeGenModule> OldBuilder = std::move(Builder);145 146      Initialize(*Ctx);147 148      if (OldBuilder)149        OldBuilder->moveLazyEmissionStates(Builder.get());150 151      return M.get();152    }153 154    void Initialize(ASTContext &Context) override {155      Ctx = &Context;156 157      M->setTargetTriple(Ctx->getTargetInfo().getTriple());158      M->setDataLayout(Ctx->getTargetInfo().getDataLayoutString());159      const auto &SDKVersion = Ctx->getTargetInfo().getSDKVersion();160      if (!SDKVersion.empty())161        M->setSDKVersion(SDKVersion);162      if (const auto *TVT = Ctx->getTargetInfo().getDarwinTargetVariantTriple())163        M->setDarwinTargetVariantTriple(TVT->getTriple());164      if (auto TVSDKVersion =165              Ctx->getTargetInfo().getDarwinTargetVariantSDKVersion())166        M->setDarwinTargetVariantSDKVersion(*TVSDKVersion);167      Builder.reset(new CodeGen::CodeGenModule(Context, FS, HeaderSearchOpts,168                                               PreprocessorOpts, CodeGenOpts,169                                               *M, Diags, CoverageInfo));170 171      for (auto &&Lib : CodeGenOpts.DependentLibraries)172        Builder->AddDependentLib(Lib);173      for (auto &&Opt : CodeGenOpts.LinkerOptions)174        Builder->AppendLinkerOptions(Opt);175    }176 177    void HandleCXXStaticMemberVarInstantiation(VarDecl *VD) override {178      if (Diags.hasErrorOccurred())179        return;180 181      Builder->HandleCXXStaticMemberVarInstantiation(VD);182    }183 184    bool HandleTopLevelDecl(DeclGroupRef DG) override {185      // Ignore interesting decls from the AST reader after IRGen is finished.186      if (IRGenFinished)187        return true; // We can't CodeGen more but pass to other consumers.188 189      // FIXME: Why not return false and abort parsing?190      if (Diags.hasUnrecoverableErrorOccurred())191        return true;192 193      HandlingTopLevelDeclRAII HandlingDecl(*this);194 195      // Make sure to emit all elements of a Decl.196      for (auto &I : DG)197        Builder->EmitTopLevelDecl(I);198 199      return true;200    }201 202    void EmitDeferredDecls() {203      if (DeferredInlineMemberFuncDefs.empty())204        return;205 206      // Emit any deferred inline method definitions. Note that more deferred207      // methods may be added during this loop, since ASTConsumer callbacks208      // can be invoked if AST inspection results in declarations being added.209      HandlingTopLevelDeclRAII HandlingDecl(*this);210      for (unsigned I = 0; I != DeferredInlineMemberFuncDefs.size(); ++I)211        Builder->EmitTopLevelDecl(DeferredInlineMemberFuncDefs[I]);212      DeferredInlineMemberFuncDefs.clear();213    }214 215    void HandleInlineFunctionDefinition(FunctionDecl *D) override {216      if (Diags.hasUnrecoverableErrorOccurred())217        return;218 219      assert(D->doesThisDeclarationHaveABody());220 221      // We may want to emit this definition. However, that decision might be222      // based on computing the linkage, and we have to defer that in case we223      // are inside of something that will change the method's final linkage,224      // e.g.225      //   typedef struct {226      //     void bar();227      //     void foo() { bar(); }228      //   } A;229      DeferredInlineMemberFuncDefs.push_back(D);230 231      // Provide some coverage mapping even for methods that aren't emitted.232      // Don't do this for templated classes though, as they may not be233      // instantiable.234      if (!D->getLexicalDeclContext()->isDependentContext())235        Builder->AddDeferredUnusedCoverageMapping(D);236    }237 238    /// HandleTagDeclDefinition - This callback is invoked each time a TagDecl239    /// to (e.g. struct, union, enum, class) is completed. This allows the240    /// client hack on the type, which can occur at any point in the file241    /// (because these can be defined in declspecs).242    void HandleTagDeclDefinition(TagDecl *D) override {243      if (Diags.hasUnrecoverableErrorOccurred())244        return;245 246      // Don't allow re-entrant calls to CodeGen triggered by PCH247      // deserialization to emit deferred decls.248      HandlingTopLevelDeclRAII HandlingDecl(*this, /*EmitDeferred=*/false);249 250      Builder->UpdateCompletedType(D);251 252      // For MSVC compatibility, treat declarations of static data members with253      // inline initializers as definitions.254      if (Ctx->getTargetInfo().getCXXABI().isMicrosoft()) {255        for (Decl *Member : D->decls()) {256          if (VarDecl *VD = dyn_cast<VarDecl>(Member)) {257            if (Ctx->isMSStaticDataMemberInlineDefinition(VD) &&258                Ctx->DeclMustBeEmitted(VD)) {259              Builder->EmitGlobal(VD);260            }261          }262        }263      }264      // For OpenMP emit declare reduction functions, if required.265      if (Ctx->getLangOpts().OpenMP) {266        for (Decl *Member : D->decls()) {267          if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(Member)) {268            if (Ctx->DeclMustBeEmitted(DRD))269              Builder->EmitGlobal(DRD);270          } else if (auto *DMD = dyn_cast<OMPDeclareMapperDecl>(Member)) {271            if (Ctx->DeclMustBeEmitted(DMD))272              Builder->EmitGlobal(DMD);273          }274        }275      }276    }277 278    void HandleTagDeclRequiredDefinition(const TagDecl *D) override {279      if (Diags.hasUnrecoverableErrorOccurred())280        return;281 282      // Don't allow re-entrant calls to CodeGen triggered by PCH283      // deserialization to emit deferred decls.284      HandlingTopLevelDeclRAII HandlingDecl(*this, /*EmitDeferred=*/false);285 286      if (CodeGen::CGDebugInfo *DI = Builder->getModuleDebugInfo())287        if (const RecordDecl *RD = dyn_cast<RecordDecl>(D))288          DI->completeRequiredType(RD);289    }290 291    void HandleTranslationUnit(ASTContext &Ctx) override {292      // Release the Builder when there is no error.293      if (!Diags.hasUnrecoverableErrorOccurred() && Builder)294        Builder->Release();295 296      // If there are errors before or when releasing the Builder, reset297      // the module to stop here before invoking the backend.298      if (Diags.hasErrorOccurred()) {299        if (Builder)300          Builder->clear();301        M.reset();302      }303 304      IRGenFinished = true;305    }306 307    void AssignInheritanceModel(CXXRecordDecl *RD) override {308      if (Diags.hasUnrecoverableErrorOccurred())309        return;310 311      Builder->RefreshTypeCacheForClass(RD);312    }313 314    void CompleteTentativeDefinition(VarDecl *D) override {315      if (Diags.hasUnrecoverableErrorOccurred())316        return;317 318      Builder->EmitTentativeDefinition(D);319    }320 321    void CompleteExternalDeclaration(DeclaratorDecl *D) override {322      Builder->EmitExternalDeclaration(D);323    }324 325    void HandleVTable(CXXRecordDecl *RD) override {326      if (Diags.hasUnrecoverableErrorOccurred())327        return;328 329      Builder->EmitVTable(RD);330    }331  };332}333 334void CodeGenerator::anchor() { }335 336CodeGenModule &CodeGenerator::CGM() {337  return static_cast<CodeGeneratorImpl*>(this)->CGM();338}339 340llvm::Module *CodeGenerator::GetModule() {341  return static_cast<CodeGeneratorImpl*>(this)->GetModule();342}343 344llvm::Module *CodeGenerator::ReleaseModule() {345  return static_cast<CodeGeneratorImpl*>(this)->ReleaseModule();346}347 348CGDebugInfo *CodeGenerator::getCGDebugInfo() {349  return static_cast<CodeGeneratorImpl*>(this)->getCGDebugInfo();350}351 352const Decl *CodeGenerator::GetDeclForMangledName(llvm::StringRef name) {353  return static_cast<CodeGeneratorImpl*>(this)->GetDeclForMangledName(name);354}355 356llvm::StringRef CodeGenerator::GetMangledName(GlobalDecl GD) {357  return static_cast<CodeGeneratorImpl *>(this)->GetMangledName(GD);358}359 360llvm::Constant *CodeGenerator::GetAddrOfGlobal(GlobalDecl global,361                                               bool isForDefinition) {362  return static_cast<CodeGeneratorImpl*>(this)363           ->GetAddrOfGlobal(global, isForDefinition);364}365 366llvm::Module *CodeGenerator::StartModule(llvm::StringRef ModuleName,367                                         llvm::LLVMContext &C) {368  return static_cast<CodeGeneratorImpl*>(this)->StartModule(ModuleName, C);369}370 371CodeGenerator *372clang::CreateLLVMCodeGen(DiagnosticsEngine &Diags, llvm::StringRef ModuleName,373                         IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,374                         const HeaderSearchOptions &HeaderSearchOpts,375                         const PreprocessorOptions &PreprocessorOpts,376                         const CodeGenOptions &CGO, llvm::LLVMContext &C,377                         CoverageSourceInfo *CoverageInfo) {378  return new CodeGeneratorImpl(Diags, ModuleName, std::move(FS),379                               HeaderSearchOpts, PreprocessorOpts, CGO, C,380                               CoverageInfo);381}382 383namespace clang {384namespace CodeGen {385std::optional<std::pair<StringRef, StringRef>>386DemangleTrapReasonInDebugInfo(StringRef FuncName) {387  static auto TrapRegex =388      llvm::Regex(llvm::formatv("^{0}\\$(.*)\\$(.*)$", ClangTrapPrefix).str());389  llvm::SmallVector<llvm::StringRef, 3> Matches;390  std::string *ErrorPtr = nullptr;391#ifndef NDEBUG392  std::string Error;393  ErrorPtr = &Error;394#endif395  if (!TrapRegex.match(FuncName, &Matches, ErrorPtr)) {396    assert(ErrorPtr && ErrorPtr->empty() && "Invalid regex pattern");397    return {};398  }399 400  if (Matches.size() != 3) {401    assert(0 && "Expected 3 matches from Regex::match");402    return {};403  }404 405  // Returns { Trap Category, Trap Message }406  return std::make_pair(Matches[1], Matches[2]);407}408} // namespace CodeGen409} // namespace clang410