xref: /freebsd/contrib/llvm-project/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp (revision 3d36053ca6d6a17d408c8f92c504e6135dc9d8df)
1  //===--- ObjectFilePCHContainerOperations.cpp -----------------------------===//
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-exception
6  //
7  //===----------------------------------------------------------------------===//
8  
9  #include "clang/CodeGen/ObjectFilePCHContainerOperations.h"
10  #include "CGDebugInfo.h"
11  #include "CodeGenModule.h"
12  #include "clang/AST/ASTContext.h"
13  #include "clang/AST/DeclObjC.h"
14  #include "clang/AST/Expr.h"
15  #include "clang/AST/RecursiveASTVisitor.h"
16  #include "clang/Basic/CodeGenOptions.h"
17  #include "clang/Basic/Diagnostic.h"
18  #include "clang/Basic/TargetInfo.h"
19  #include "clang/CodeGen/BackendUtil.h"
20  #include "clang/Frontend/CompilerInstance.h"
21  #include "clang/Lex/HeaderSearch.h"
22  #include "clang/Lex/Preprocessor.h"
23  #include "llvm/ADT/StringRef.h"
24  #include "llvm/Bitstream/BitstreamReader.h"
25  #include "llvm/DebugInfo/DWARF/DWARFContext.h"
26  #include "llvm/IR/Constants.h"
27  #include "llvm/IR/DataLayout.h"
28  #include "llvm/IR/LLVMContext.h"
29  #include "llvm/IR/Module.h"
30  #include "llvm/MC/TargetRegistry.h"
31  #include "llvm/Object/COFF.h"
32  #include "llvm/Object/ObjectFile.h"
33  #include "llvm/Support/Path.h"
34  #include <memory>
35  #include <utility>
36  
37  using namespace clang;
38  
39  #define DEBUG_TYPE "pchcontainer"
40  
41  namespace {
42  class PCHContainerGenerator : public ASTConsumer {
43    DiagnosticsEngine &Diags;
44    const std::string MainFileName;
45    const std::string OutputFileName;
46    ASTContext *Ctx;
47    ModuleMap &MMap;
48    IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS;
49    const HeaderSearchOptions &HeaderSearchOpts;
50    const PreprocessorOptions &PreprocessorOpts;
51    CodeGenOptions CodeGenOpts;
52    const TargetOptions TargetOpts;
53    LangOptions LangOpts;
54    std::unique_ptr<llvm::LLVMContext> VMContext;
55    std::unique_ptr<llvm::Module> M;
56    std::unique_ptr<CodeGen::CodeGenModule> Builder;
57    std::unique_ptr<raw_pwrite_stream> OS;
58    std::shared_ptr<PCHBuffer> Buffer;
59  
60    /// Visit every type and emit debug info for it.
61    struct DebugTypeVisitor : public RecursiveASTVisitor<DebugTypeVisitor> {
62      clang::CodeGen::CGDebugInfo &DI;
63      ASTContext &Ctx;
64      DebugTypeVisitor(clang::CodeGen::CGDebugInfo &DI, ASTContext &Ctx)
65          : DI(DI), Ctx(Ctx) {}
66  
67      /// Determine whether this type can be represented in DWARF.
68      static bool CanRepresent(const Type *Ty) {
69        return !Ty->isDependentType() && !Ty->isUndeducedType();
70      }
71  
72      bool VisitImportDecl(ImportDecl *D) {
73        if (!D->getImportedOwningModule())
74          DI.EmitImportDecl(*D);
75        return true;
76      }
77  
78      bool VisitTypeDecl(TypeDecl *D) {
79        // TagDecls may be deferred until after all decls have been merged and we
80        // know the complete type. Pure forward declarations will be skipped, but
81        // they don't need to be emitted into the module anyway.
82        if (auto *TD = dyn_cast<TagDecl>(D))
83          if (!TD->isCompleteDefinition())
84            return true;
85  
86        QualType QualTy = Ctx.getTypeDeclType(D);
87        if (!QualTy.isNull() && CanRepresent(QualTy.getTypePtr()))
88          DI.getOrCreateStandaloneType(QualTy, D->getLocation());
89        return true;
90      }
91  
92      bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
93        QualType QualTy(D->getTypeForDecl(), 0);
94        if (!QualTy.isNull() && CanRepresent(QualTy.getTypePtr()))
95          DI.getOrCreateStandaloneType(QualTy, D->getLocation());
96        return true;
97      }
98  
99      bool VisitFunctionDecl(FunctionDecl *D) {
100        // Skip deduction guides.
101        if (isa<CXXDeductionGuideDecl>(D))
102          return true;
103  
104        if (isa<CXXMethodDecl>(D))
105          // This is not yet supported. Constructing the `this' argument
106          // mandates a CodeGenFunction.
107          return true;
108  
109        SmallVector<QualType, 16> ArgTypes;
110        for (auto *i : D->parameters())
111          ArgTypes.push_back(i->getType());
112        QualType RetTy = D->getReturnType();
113        QualType FnTy = Ctx.getFunctionType(RetTy, ArgTypes,
114                                            FunctionProtoType::ExtProtoInfo());
115        if (CanRepresent(FnTy.getTypePtr()))
116          DI.EmitFunctionDecl(D, D->getLocation(), FnTy);
117        return true;
118      }
119  
120      bool VisitObjCMethodDecl(ObjCMethodDecl *D) {
121        if (!D->getClassInterface())
122          return true;
123  
124        bool selfIsPseudoStrong, selfIsConsumed;
125        SmallVector<QualType, 16> ArgTypes;
126        ArgTypes.push_back(D->getSelfType(Ctx, D->getClassInterface(),
127                                          selfIsPseudoStrong, selfIsConsumed));
128        ArgTypes.push_back(Ctx.getObjCSelType());
129        for (auto *i : D->parameters())
130          ArgTypes.push_back(i->getType());
131        QualType RetTy = D->getReturnType();
132        QualType FnTy = Ctx.getFunctionType(RetTy, ArgTypes,
133                                            FunctionProtoType::ExtProtoInfo());
134        if (CanRepresent(FnTy.getTypePtr()))
135          DI.EmitFunctionDecl(D, D->getLocation(), FnTy);
136        return true;
137      }
138    };
139  
140  public:
141    PCHContainerGenerator(CompilerInstance &CI, const std::string &MainFileName,
142                          const std::string &OutputFileName,
143                          std::unique_ptr<raw_pwrite_stream> OS,
144                          std::shared_ptr<PCHBuffer> Buffer)
145        : Diags(CI.getDiagnostics()), MainFileName(MainFileName),
146          OutputFileName(OutputFileName), Ctx(nullptr),
147          MMap(CI.getPreprocessor().getHeaderSearchInfo().getModuleMap()),
148          FS(&CI.getVirtualFileSystem()),
149          HeaderSearchOpts(CI.getHeaderSearchOpts()),
150          PreprocessorOpts(CI.getPreprocessorOpts()),
151          TargetOpts(CI.getTargetOpts()), LangOpts(CI.getLangOpts()),
152          OS(std::move(OS)), Buffer(std::move(Buffer)) {
153      // The debug info output isn't affected by CodeModel and
154      // ThreadModel, but the backend expects them to be nonempty.
155      CodeGenOpts.CodeModel = "default";
156      LangOpts.setThreadModel(LangOptions::ThreadModelKind::Single);
157      CodeGenOpts.DebugTypeExtRefs = true;
158      // When building a module MainFileName is the name of the modulemap file.
159      CodeGenOpts.MainFileName =
160          LangOpts.CurrentModule.empty() ? MainFileName : LangOpts.CurrentModule;
161      CodeGenOpts.setDebugInfo(llvm::codegenoptions::FullDebugInfo);
162      CodeGenOpts.setDebuggerTuning(CI.getCodeGenOpts().getDebuggerTuning());
163      CodeGenOpts.DebugPrefixMap =
164          CI.getInvocation().getCodeGenOpts().DebugPrefixMap;
165      CodeGenOpts.DebugStrictDwarf = CI.getCodeGenOpts().DebugStrictDwarf;
166    }
167  
168    ~PCHContainerGenerator() override = default;
169  
170    void Initialize(ASTContext &Context) override {
171      assert(!Ctx && "initialized multiple times");
172  
173      Ctx = &Context;
174      VMContext.reset(new llvm::LLVMContext());
175      M.reset(new llvm::Module(MainFileName, *VMContext));
176      M->setDataLayout(Ctx->getTargetInfo().getDataLayoutString());
177      Builder.reset(new CodeGen::CodeGenModule(
178          *Ctx, FS, HeaderSearchOpts, PreprocessorOpts, CodeGenOpts, *M, Diags));
179  
180      // Prepare CGDebugInfo to emit debug info for a clang module.
181      auto *DI = Builder->getModuleDebugInfo();
182      StringRef ModuleName = llvm::sys::path::filename(MainFileName);
183      DI->setPCHDescriptor(
184          {ModuleName, "", OutputFileName, ASTFileSignature::createDISentinel()});
185      DI->setModuleMap(MMap);
186    }
187  
188    bool HandleTopLevelDecl(DeclGroupRef D) override {
189      if (Diags.hasErrorOccurred())
190        return true;
191  
192      // Collect debug info for all decls in this group.
193      for (auto *I : D)
194        if (!I->isFromASTFile()) {
195          DebugTypeVisitor DTV(*Builder->getModuleDebugInfo(), *Ctx);
196          DTV.TraverseDecl(I);
197        }
198      return true;
199    }
200  
201    void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override {
202      HandleTopLevelDecl(D);
203    }
204  
205    void HandleTagDeclDefinition(TagDecl *D) override {
206      if (Diags.hasErrorOccurred())
207        return;
208  
209      if (D->isFromASTFile())
210        return;
211  
212      // Anonymous tag decls are deferred until we are building their declcontext.
213      if (D->getName().empty())
214        return;
215  
216      // Defer tag decls until their declcontext is complete.
217      auto *DeclCtx = D->getDeclContext();
218      while (DeclCtx) {
219        if (auto *D = dyn_cast<TagDecl>(DeclCtx))
220          if (!D->isCompleteDefinition())
221            return;
222        DeclCtx = DeclCtx->getParent();
223      }
224  
225      DebugTypeVisitor DTV(*Builder->getModuleDebugInfo(), *Ctx);
226      DTV.TraverseDecl(D);
227      Builder->UpdateCompletedType(D);
228    }
229  
230    void HandleTagDeclRequiredDefinition(const TagDecl *D) override {
231      if (Diags.hasErrorOccurred())
232        return;
233  
234      if (const RecordDecl *RD = dyn_cast<RecordDecl>(D))
235        Builder->getModuleDebugInfo()->completeRequiredType(RD);
236    }
237  
238    void HandleImplicitImportDecl(ImportDecl *D) override {
239      if (!D->getImportedOwningModule())
240        Builder->getModuleDebugInfo()->EmitImportDecl(*D);
241    }
242  
243    /// Emit a container holding the serialized AST.
244    void HandleTranslationUnit(ASTContext &Ctx) override {
245      assert(M && VMContext && Builder);
246      // Delete these on function exit.
247      std::unique_ptr<llvm::LLVMContext> VMContext = std::move(this->VMContext);
248      std::unique_ptr<llvm::Module> M = std::move(this->M);
249      std::unique_ptr<CodeGen::CodeGenModule> Builder = std::move(this->Builder);
250  
251      if (Diags.hasErrorOccurred())
252        return;
253  
254      M->setTargetTriple(Ctx.getTargetInfo().getTriple().getTriple());
255      M->setDataLayout(Ctx.getTargetInfo().getDataLayoutString());
256  
257      // PCH files don't have a signature field in the control block,
258      // but LLVM detects DWO CUs by looking for a non-zero DWO id.
259      // We use the lower 64 bits for debug info.
260  
261      uint64_t Signature =
262          Buffer->Signature ? Buffer->Signature.truncatedValue() : ~1ULL;
263  
264      Builder->getModuleDebugInfo()->setDwoId(Signature);
265  
266      // Finalize the Builder.
267      if (Builder)
268        Builder->Release();
269  
270      // Ensure the target exists.
271      std::string Error;
272      auto Triple = Ctx.getTargetInfo().getTriple();
273      if (!llvm::TargetRegistry::lookupTarget(Triple.getTriple(), Error))
274        llvm::report_fatal_error(llvm::Twine(Error));
275  
276      // Emit the serialized Clang AST into its own section.
277      assert(Buffer->IsComplete && "serialization did not complete");
278      auto &SerializedAST = Buffer->Data;
279      auto Size = SerializedAST.size();
280  
281      if (Triple.isOSBinFormatWasm()) {
282        // Emit __clangast in custom section instead of named data segment
283        // to find it while iterating sections.
284        // This could be avoided if all data segements (the wasm sense) were
285        // represented as their own sections (in the llvm sense).
286        // TODO: https://github.com/WebAssembly/tool-conventions/issues/138
287        llvm::NamedMDNode *MD =
288            M->getOrInsertNamedMetadata("wasm.custom_sections");
289        llvm::Metadata *Ops[2] = {
290            llvm::MDString::get(*VMContext, "__clangast"),
291            llvm::MDString::get(*VMContext,
292                                StringRef(SerializedAST.data(), Size))};
293        auto *NameAndContent = llvm::MDTuple::get(*VMContext, Ops);
294        MD->addOperand(NameAndContent);
295      } else {
296        auto Int8Ty = llvm::Type::getInt8Ty(*VMContext);
297        auto *Ty = llvm::ArrayType::get(Int8Ty, Size);
298        auto *Data = llvm::ConstantDataArray::getString(
299            *VMContext, StringRef(SerializedAST.data(), Size),
300            /*AddNull=*/false);
301        auto *ASTSym = new llvm::GlobalVariable(
302            *M, Ty, /*constant*/ true, llvm::GlobalVariable::InternalLinkage,
303            Data, "__clang_ast");
304        // The on-disk hashtable needs to be aligned.
305        ASTSym->setAlignment(llvm::Align(8));
306  
307        // Mach-O also needs a segment name.
308        if (Triple.isOSBinFormatMachO())
309          ASTSym->setSection("__CLANG,__clangast");
310        // COFF has an eight character length limit.
311        else if (Triple.isOSBinFormatCOFF())
312          ASTSym->setSection("clangast");
313        else
314          ASTSym->setSection("__clangast");
315      }
316  
317      LLVM_DEBUG({
318        // Print the IR for the PCH container to the debug output.
319        llvm::SmallString<0> Buffer;
320        clang::EmitBackendOutput(
321            Diags, HeaderSearchOpts, CodeGenOpts, TargetOpts, LangOpts,
322            Ctx.getTargetInfo().getDataLayoutString(), M.get(),
323            BackendAction::Backend_EmitLL, FS,
324            std::make_unique<llvm::raw_svector_ostream>(Buffer));
325        llvm::dbgs() << Buffer;
326      });
327  
328      // Use the LLVM backend to emit the pch container.
329      clang::EmitBackendOutput(Diags, HeaderSearchOpts, CodeGenOpts, TargetOpts,
330                               LangOpts,
331                               Ctx.getTargetInfo().getDataLayoutString(), M.get(),
332                               BackendAction::Backend_EmitObj, FS, std::move(OS));
333  
334      // Free the memory for the temporary buffer.
335      llvm::SmallVector<char, 0> Empty;
336      SerializedAST = std::move(Empty);
337    }
338  };
339  
340  } // anonymous namespace
341  
342  std::unique_ptr<ASTConsumer>
343  ObjectFilePCHContainerWriter::CreatePCHContainerGenerator(
344      CompilerInstance &CI, const std::string &MainFileName,
345      const std::string &OutputFileName,
346      std::unique_ptr<llvm::raw_pwrite_stream> OS,
347      std::shared_ptr<PCHBuffer> Buffer) const {
348    return std::make_unique<PCHContainerGenerator>(
349        CI, MainFileName, OutputFileName, std::move(OS), Buffer);
350  }
351  
352  ArrayRef<StringRef> ObjectFilePCHContainerReader::getFormats() const {
353    static StringRef Formats[] = {"obj", "raw"};
354    return Formats;
355  }
356  
357  StringRef
358  ObjectFilePCHContainerReader::ExtractPCH(llvm::MemoryBufferRef Buffer) const {
359    StringRef PCH;
360    auto OFOrErr = llvm::object::ObjectFile::createObjectFile(Buffer);
361    if (OFOrErr) {
362      auto &OF = OFOrErr.get();
363      bool IsCOFF = isa<llvm::object::COFFObjectFile>(*OF);
364      // Find the clang AST section in the container.
365      for (auto &Section : OF->sections()) {
366        StringRef Name;
367        if (Expected<StringRef> NameOrErr = Section.getName())
368          Name = *NameOrErr;
369        else
370          consumeError(NameOrErr.takeError());
371  
372        if ((!IsCOFF && Name == "__clangast") || (IsCOFF && Name == "clangast")) {
373          if (Expected<StringRef> E = Section.getContents())
374            return *E;
375          else {
376            handleAllErrors(E.takeError(), [&](const llvm::ErrorInfoBase &EIB) {
377              EIB.log(llvm::errs());
378            });
379            return "";
380          }
381        }
382      }
383    }
384    handleAllErrors(OFOrErr.takeError(), [&](const llvm::ErrorInfoBase &EIB) {
385      if (EIB.convertToErrorCode() ==
386          llvm::object::object_error::invalid_file_type)
387        // As a fallback, treat the buffer as a raw AST.
388        PCH = Buffer.getBuffer();
389      else
390        EIB.log(llvm::errs());
391    });
392    return PCH;
393  }
394