Home | History | Annotate | Download | only in CodeGen
      1 //===--- ModuleBuilder.cpp - Emit LLVM Code from ASTs ---------------------===//
      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 // This builds an AST and converts it to LLVM Code.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "clang/CodeGen/ModuleBuilder.h"
     15 #include "CGDebugInfo.h"
     16 #include "CodeGenModule.h"
     17 #include "clang/AST/ASTContext.h"
     18 #include "clang/AST/DeclObjC.h"
     19 #include "clang/AST/Expr.h"
     20 #include "clang/Basic/Diagnostic.h"
     21 #include "clang/Basic/TargetInfo.h"
     22 #include "clang/Frontend/CodeGenOptions.h"
     23 #include "llvm/ADT/StringRef.h"
     24 #include "llvm/IR/DataLayout.h"
     25 #include "llvm/IR/LLVMContext.h"
     26 #include "llvm/IR/Module.h"
     27 #include <memory>
     28 using namespace clang;
     29 
     30 namespace {
     31   class CodeGeneratorImpl : public CodeGenerator {
     32     DiagnosticsEngine &Diags;
     33     std::unique_ptr<const llvm::DataLayout> TD;
     34     ASTContext *Ctx;
     35     const CodeGenOptions CodeGenOpts;  // Intentionally copied in.
     36   protected:
     37     std::unique_ptr<llvm::Module> M;
     38     std::unique_ptr<CodeGen::CodeGenModule> Builder;
     39 
     40   public:
     41     CodeGeneratorImpl(DiagnosticsEngine &diags, const std::string& ModuleName,
     42                       const CodeGenOptions &CGO, llvm::LLVMContext& C)
     43       : Diags(diags), CodeGenOpts(CGO),
     44         M(new llvm::Module(ModuleName, C)) {}
     45 
     46     virtual ~CodeGeneratorImpl() {}
     47 
     48     llvm::Module* GetModule() override {
     49       return M.get();
     50     }
     51 
     52     const Decl *GetDeclForMangledName(StringRef MangledName) override {
     53       GlobalDecl Result;
     54       if (!Builder->lookupRepresentativeDecl(MangledName, Result))
     55         return nullptr;
     56       const Decl *D = Result.getCanonicalDecl().getDecl();
     57       if (auto FD = dyn_cast<FunctionDecl>(D)) {
     58         if (FD->hasBody(FD))
     59           return FD;
     60       } else if (auto TD = dyn_cast<TagDecl>(D)) {
     61         if (auto Def = TD->getDefinition())
     62           return Def;
     63       }
     64       return D;
     65     }
     66 
     67     llvm::Module *ReleaseModule() override { return M.release(); }
     68 
     69     void Initialize(ASTContext &Context) override {
     70       Ctx = &Context;
     71 
     72       M->setTargetTriple(Ctx->getTargetInfo().getTriple().getTriple());
     73       M->setDataLayout(Ctx->getTargetInfo().getTargetDescription());
     74       TD.reset(new llvm::DataLayout(Ctx->getTargetInfo().getTargetDescription()));
     75       Builder.reset(new CodeGen::CodeGenModule(Context, CodeGenOpts, *M, *TD,
     76                                                Diags));
     77 
     78       for (size_t i = 0, e = CodeGenOpts.DependentLibraries.size(); i < e; ++i)
     79         HandleDependentLibrary(CodeGenOpts.DependentLibraries[i]);
     80     }
     81 
     82     void HandleCXXStaticMemberVarInstantiation(VarDecl *VD) override {
     83       if (Diags.hasErrorOccurred())
     84         return;
     85 
     86       Builder->HandleCXXStaticMemberVarInstantiation(VD);
     87     }
     88 
     89     bool HandleTopLevelDecl(DeclGroupRef DG) override {
     90       if (Diags.hasErrorOccurred())
     91         return true;
     92 
     93       // Make sure to emit all elements of a Decl.
     94       for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
     95         Builder->EmitTopLevelDecl(*I);
     96 
     97       // Emit any deferred inline method definitions.
     98       for (CXXMethodDecl *MD : DeferredInlineMethodDefinitions)
     99         Builder->EmitTopLevelDecl(MD);
    100       DeferredInlineMethodDefinitions.clear();
    101 
    102       return true;
    103     }
    104 
    105     void HandleInlineMethodDefinition(CXXMethodDecl *D) override {
    106       if (Diags.hasErrorOccurred())
    107         return;
    108 
    109       assert(D->doesThisDeclarationHaveABody());
    110 
    111       // We may want to emit this definition. However, that decision might be
    112       // based on computing the linkage, and we have to defer that in case we
    113       // are inside of something that will change the method's final linkage,
    114       // e.g.
    115       //   typedef struct {
    116       //     void bar();
    117       //     void foo() { bar(); }
    118       //   } A;
    119       DeferredInlineMethodDefinitions.push_back(D);
    120     }
    121 
    122     /// HandleTagDeclDefinition - This callback is invoked each time a TagDecl
    123     /// to (e.g. struct, union, enum, class) is completed. This allows the
    124     /// client hack on the type, which can occur at any point in the file
    125     /// (because these can be defined in declspecs).
    126     void HandleTagDeclDefinition(TagDecl *D) override {
    127       if (Diags.hasErrorOccurred())
    128         return;
    129 
    130       Builder->UpdateCompletedType(D);
    131     }
    132 
    133     void HandleTagDeclRequiredDefinition(const TagDecl *D) override {
    134       if (Diags.hasErrorOccurred())
    135         return;
    136 
    137       if (CodeGen::CGDebugInfo *DI = Builder->getModuleDebugInfo())
    138         if (const RecordDecl *RD = dyn_cast<RecordDecl>(D))
    139           DI->completeRequiredType(RD);
    140     }
    141 
    142     void HandleTranslationUnit(ASTContext &Ctx) override {
    143       if (Diags.hasErrorOccurred()) {
    144         if (Builder)
    145           Builder->clear();
    146         M.reset();
    147         return;
    148       }
    149 
    150       if (Builder)
    151         Builder->Release();
    152     }
    153 
    154     void CompleteTentativeDefinition(VarDecl *D) override {
    155       if (Diags.hasErrorOccurred())
    156         return;
    157 
    158       Builder->EmitTentativeDefinition(D);
    159     }
    160 
    161     void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) override {
    162       if (Diags.hasErrorOccurred())
    163         return;
    164 
    165       Builder->EmitVTable(RD, DefinitionRequired);
    166     }
    167 
    168     void HandleLinkerOptionPragma(llvm::StringRef Opts) override {
    169       Builder->AppendLinkerOptions(Opts);
    170     }
    171 
    172     void HandleDetectMismatch(llvm::StringRef Name,
    173                               llvm::StringRef Value) override {
    174       Builder->AddDetectMismatch(Name, Value);
    175     }
    176 
    177     void HandleDependentLibrary(llvm::StringRef Lib) override {
    178       Builder->AddDependentLib(Lib);
    179     }
    180 
    181   private:
    182     std::vector<CXXMethodDecl *> DeferredInlineMethodDefinitions;
    183   };
    184 }
    185 
    186 void CodeGenerator::anchor() { }
    187 
    188 CodeGenerator *clang::CreateLLVMCodeGen(DiagnosticsEngine &Diags,
    189                                         const std::string& ModuleName,
    190                                         const CodeGenOptions &CGO,
    191                                         const TargetOptions &/*TO*/,
    192                                         llvm::LLVMContext& C) {
    193   return new CodeGeneratorImpl(Diags, ModuleName, CGO, C);
    194 }
    195