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