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