xref: /netbsd-src/external/apache2/llvm/dist/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp (revision e038c9c4676b0f19b1b7dd08a940c6ed64a6d5ae)
17330f729Sjoerg //===--- ObjectFilePCHContainerOperations.cpp -----------------------------===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg 
97330f729Sjoerg #include "clang/CodeGen/ObjectFilePCHContainerOperations.h"
107330f729Sjoerg #include "CGDebugInfo.h"
117330f729Sjoerg #include "CodeGenModule.h"
127330f729Sjoerg #include "clang/AST/ASTContext.h"
137330f729Sjoerg #include "clang/AST/DeclObjC.h"
147330f729Sjoerg #include "clang/AST/Expr.h"
157330f729Sjoerg #include "clang/AST/RecursiveASTVisitor.h"
167330f729Sjoerg #include "clang/Basic/CodeGenOptions.h"
177330f729Sjoerg #include "clang/Basic/Diagnostic.h"
187330f729Sjoerg #include "clang/Basic/TargetInfo.h"
197330f729Sjoerg #include "clang/CodeGen/BackendUtil.h"
207330f729Sjoerg #include "clang/Frontend/CompilerInstance.h"
217330f729Sjoerg #include "clang/Lex/HeaderSearch.h"
227330f729Sjoerg #include "clang/Lex/Preprocessor.h"
237330f729Sjoerg #include "llvm/ADT/StringRef.h"
247330f729Sjoerg #include "llvm/Bitstream/BitstreamReader.h"
257330f729Sjoerg #include "llvm/DebugInfo/DWARF/DWARFContext.h"
267330f729Sjoerg #include "llvm/IR/Constants.h"
277330f729Sjoerg #include "llvm/IR/DataLayout.h"
287330f729Sjoerg #include "llvm/IR/LLVMContext.h"
297330f729Sjoerg #include "llvm/IR/Module.h"
307330f729Sjoerg #include "llvm/Object/COFF.h"
317330f729Sjoerg #include "llvm/Object/ObjectFile.h"
327330f729Sjoerg #include "llvm/Support/Path.h"
337330f729Sjoerg #include "llvm/Support/TargetRegistry.h"
347330f729Sjoerg #include <memory>
357330f729Sjoerg #include <utility>
367330f729Sjoerg 
377330f729Sjoerg using namespace clang;
387330f729Sjoerg 
397330f729Sjoerg #define DEBUG_TYPE "pchcontainer"
407330f729Sjoerg 
417330f729Sjoerg namespace {
427330f729Sjoerg class PCHContainerGenerator : public ASTConsumer {
437330f729Sjoerg   DiagnosticsEngine &Diags;
447330f729Sjoerg   const std::string MainFileName;
457330f729Sjoerg   const std::string OutputFileName;
467330f729Sjoerg   ASTContext *Ctx;
477330f729Sjoerg   ModuleMap &MMap;
487330f729Sjoerg   const HeaderSearchOptions &HeaderSearchOpts;
497330f729Sjoerg   const PreprocessorOptions &PreprocessorOpts;
507330f729Sjoerg   CodeGenOptions CodeGenOpts;
517330f729Sjoerg   const TargetOptions TargetOpts;
52*e038c9c4Sjoerg   LangOptions LangOpts;
537330f729Sjoerg   std::unique_ptr<llvm::LLVMContext> VMContext;
547330f729Sjoerg   std::unique_ptr<llvm::Module> M;
557330f729Sjoerg   std::unique_ptr<CodeGen::CodeGenModule> Builder;
567330f729Sjoerg   std::unique_ptr<raw_pwrite_stream> OS;
577330f729Sjoerg   std::shared_ptr<PCHBuffer> Buffer;
587330f729Sjoerg 
597330f729Sjoerg   /// Visit every type and emit debug info for it.
607330f729Sjoerg   struct DebugTypeVisitor : public RecursiveASTVisitor<DebugTypeVisitor> {
617330f729Sjoerg     clang::CodeGen::CGDebugInfo &DI;
627330f729Sjoerg     ASTContext &Ctx;
DebugTypeVisitor__anon115c17220111::PCHContainerGenerator::DebugTypeVisitor637330f729Sjoerg     DebugTypeVisitor(clang::CodeGen::CGDebugInfo &DI, ASTContext &Ctx)
647330f729Sjoerg         : DI(DI), Ctx(Ctx) {}
657330f729Sjoerg 
667330f729Sjoerg     /// Determine whether this type can be represented in DWARF.
CanRepresent__anon115c17220111::PCHContainerGenerator::DebugTypeVisitor677330f729Sjoerg     static bool CanRepresent(const Type *Ty) {
687330f729Sjoerg       return !Ty->isDependentType() && !Ty->isUndeducedType();
697330f729Sjoerg     }
707330f729Sjoerg 
VisitImportDecl__anon115c17220111::PCHContainerGenerator::DebugTypeVisitor717330f729Sjoerg     bool VisitImportDecl(ImportDecl *D) {
727330f729Sjoerg       if (!D->getImportedOwningModule())
737330f729Sjoerg         DI.EmitImportDecl(*D);
747330f729Sjoerg       return true;
757330f729Sjoerg     }
767330f729Sjoerg 
VisitTypeDecl__anon115c17220111::PCHContainerGenerator::DebugTypeVisitor777330f729Sjoerg     bool VisitTypeDecl(TypeDecl *D) {
787330f729Sjoerg       // TagDecls may be deferred until after all decls have been merged and we
797330f729Sjoerg       // know the complete type. Pure forward declarations will be skipped, but
807330f729Sjoerg       // they don't need to be emitted into the module anyway.
817330f729Sjoerg       if (auto *TD = dyn_cast<TagDecl>(D))
827330f729Sjoerg         if (!TD->isCompleteDefinition())
837330f729Sjoerg           return true;
847330f729Sjoerg 
857330f729Sjoerg       QualType QualTy = Ctx.getTypeDeclType(D);
867330f729Sjoerg       if (!QualTy.isNull() && CanRepresent(QualTy.getTypePtr()))
877330f729Sjoerg         DI.getOrCreateStandaloneType(QualTy, D->getLocation());
887330f729Sjoerg       return true;
897330f729Sjoerg     }
907330f729Sjoerg 
VisitObjCInterfaceDecl__anon115c17220111::PCHContainerGenerator::DebugTypeVisitor917330f729Sjoerg     bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
927330f729Sjoerg       QualType QualTy(D->getTypeForDecl(), 0);
937330f729Sjoerg       if (!QualTy.isNull() && CanRepresent(QualTy.getTypePtr()))
947330f729Sjoerg         DI.getOrCreateStandaloneType(QualTy, D->getLocation());
957330f729Sjoerg       return true;
967330f729Sjoerg     }
977330f729Sjoerg 
VisitFunctionDecl__anon115c17220111::PCHContainerGenerator::DebugTypeVisitor987330f729Sjoerg     bool VisitFunctionDecl(FunctionDecl *D) {
997330f729Sjoerg       if (isa<CXXMethodDecl>(D))
1007330f729Sjoerg         // This is not yet supported. Constructing the `this' argument
1017330f729Sjoerg         // mandates a CodeGenFunction.
1027330f729Sjoerg         return true;
1037330f729Sjoerg 
1047330f729Sjoerg       SmallVector<QualType, 16> ArgTypes;
1057330f729Sjoerg       for (auto i : D->parameters())
1067330f729Sjoerg         ArgTypes.push_back(i->getType());
1077330f729Sjoerg       QualType RetTy = D->getReturnType();
1087330f729Sjoerg       QualType FnTy = Ctx.getFunctionType(RetTy, ArgTypes,
1097330f729Sjoerg                                           FunctionProtoType::ExtProtoInfo());
1107330f729Sjoerg       if (CanRepresent(FnTy.getTypePtr()))
1117330f729Sjoerg         DI.EmitFunctionDecl(D, D->getLocation(), FnTy);
1127330f729Sjoerg       return true;
1137330f729Sjoerg     }
1147330f729Sjoerg 
VisitObjCMethodDecl__anon115c17220111::PCHContainerGenerator::DebugTypeVisitor1157330f729Sjoerg     bool VisitObjCMethodDecl(ObjCMethodDecl *D) {
1167330f729Sjoerg       if (!D->getClassInterface())
1177330f729Sjoerg         return true;
1187330f729Sjoerg 
1197330f729Sjoerg       bool selfIsPseudoStrong, selfIsConsumed;
1207330f729Sjoerg       SmallVector<QualType, 16> ArgTypes;
1217330f729Sjoerg       ArgTypes.push_back(D->getSelfType(Ctx, D->getClassInterface(),
1227330f729Sjoerg                                         selfIsPseudoStrong, selfIsConsumed));
1237330f729Sjoerg       ArgTypes.push_back(Ctx.getObjCSelType());
1247330f729Sjoerg       for (auto i : D->parameters())
1257330f729Sjoerg         ArgTypes.push_back(i->getType());
1267330f729Sjoerg       QualType RetTy = D->getReturnType();
1277330f729Sjoerg       QualType FnTy = Ctx.getFunctionType(RetTy, ArgTypes,
1287330f729Sjoerg                                           FunctionProtoType::ExtProtoInfo());
1297330f729Sjoerg       if (CanRepresent(FnTy.getTypePtr()))
1307330f729Sjoerg         DI.EmitFunctionDecl(D, D->getLocation(), FnTy);
1317330f729Sjoerg       return true;
1327330f729Sjoerg     }
1337330f729Sjoerg   };
1347330f729Sjoerg 
1357330f729Sjoerg public:
PCHContainerGenerator(CompilerInstance & CI,const std::string & MainFileName,const std::string & OutputFileName,std::unique_ptr<raw_pwrite_stream> OS,std::shared_ptr<PCHBuffer> Buffer)1367330f729Sjoerg   PCHContainerGenerator(CompilerInstance &CI, const std::string &MainFileName,
1377330f729Sjoerg                         const std::string &OutputFileName,
1387330f729Sjoerg                         std::unique_ptr<raw_pwrite_stream> OS,
1397330f729Sjoerg                         std::shared_ptr<PCHBuffer> Buffer)
1407330f729Sjoerg       : Diags(CI.getDiagnostics()), MainFileName(MainFileName),
1417330f729Sjoerg         OutputFileName(OutputFileName), Ctx(nullptr),
1427330f729Sjoerg         MMap(CI.getPreprocessor().getHeaderSearchInfo().getModuleMap()),
1437330f729Sjoerg         HeaderSearchOpts(CI.getHeaderSearchOpts()),
1447330f729Sjoerg         PreprocessorOpts(CI.getPreprocessorOpts()),
1457330f729Sjoerg         TargetOpts(CI.getTargetOpts()), LangOpts(CI.getLangOpts()),
1467330f729Sjoerg         OS(std::move(OS)), Buffer(std::move(Buffer)) {
1477330f729Sjoerg     // The debug info output isn't affected by CodeModel and
1487330f729Sjoerg     // ThreadModel, but the backend expects them to be nonempty.
1497330f729Sjoerg     CodeGenOpts.CodeModel = "default";
150*e038c9c4Sjoerg     LangOpts.setThreadModel(LangOptions::ThreadModelKind::Single);
1517330f729Sjoerg     CodeGenOpts.DebugTypeExtRefs = true;
1527330f729Sjoerg     // When building a module MainFileName is the name of the modulemap file.
1537330f729Sjoerg     CodeGenOpts.MainFileName =
1547330f729Sjoerg         LangOpts.CurrentModule.empty() ? MainFileName : LangOpts.CurrentModule;
1557330f729Sjoerg     CodeGenOpts.setDebugInfo(codegenoptions::FullDebugInfo);
1567330f729Sjoerg     CodeGenOpts.setDebuggerTuning(CI.getCodeGenOpts().getDebuggerTuning());
1577330f729Sjoerg     CodeGenOpts.DebugPrefixMap =
1587330f729Sjoerg         CI.getInvocation().getCodeGenOpts().DebugPrefixMap;
1597330f729Sjoerg   }
1607330f729Sjoerg 
1617330f729Sjoerg   ~PCHContainerGenerator() override = default;
1627330f729Sjoerg 
Initialize(ASTContext & Context)1637330f729Sjoerg   void Initialize(ASTContext &Context) override {
1647330f729Sjoerg     assert(!Ctx && "initialized multiple times");
1657330f729Sjoerg 
1667330f729Sjoerg     Ctx = &Context;
1677330f729Sjoerg     VMContext.reset(new llvm::LLVMContext());
1687330f729Sjoerg     M.reset(new llvm::Module(MainFileName, *VMContext));
169*e038c9c4Sjoerg     M->setDataLayout(Ctx->getTargetInfo().getDataLayoutString());
1707330f729Sjoerg     Builder.reset(new CodeGen::CodeGenModule(
1717330f729Sjoerg         *Ctx, HeaderSearchOpts, PreprocessorOpts, CodeGenOpts, *M, Diags));
1727330f729Sjoerg 
1737330f729Sjoerg     // Prepare CGDebugInfo to emit debug info for a clang module.
1747330f729Sjoerg     auto *DI = Builder->getModuleDebugInfo();
1757330f729Sjoerg     StringRef ModuleName = llvm::sys::path::filename(MainFileName);
176*e038c9c4Sjoerg     DI->setPCHDescriptor(
177*e038c9c4Sjoerg         {ModuleName, "", OutputFileName, ASTFileSignature::createDISentinel()});
1787330f729Sjoerg     DI->setModuleMap(MMap);
1797330f729Sjoerg   }
1807330f729Sjoerg 
HandleTopLevelDecl(DeclGroupRef D)1817330f729Sjoerg   bool HandleTopLevelDecl(DeclGroupRef D) override {
1827330f729Sjoerg     if (Diags.hasErrorOccurred())
1837330f729Sjoerg       return true;
1847330f729Sjoerg 
1857330f729Sjoerg     // Collect debug info for all decls in this group.
1867330f729Sjoerg     for (auto *I : D)
1877330f729Sjoerg       if (!I->isFromASTFile()) {
1887330f729Sjoerg         DebugTypeVisitor DTV(*Builder->getModuleDebugInfo(), *Ctx);
1897330f729Sjoerg         DTV.TraverseDecl(I);
1907330f729Sjoerg       }
1917330f729Sjoerg     return true;
1927330f729Sjoerg   }
1937330f729Sjoerg 
HandleTopLevelDeclInObjCContainer(DeclGroupRef D)1947330f729Sjoerg   void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override {
1957330f729Sjoerg     HandleTopLevelDecl(D);
1967330f729Sjoerg   }
1977330f729Sjoerg 
HandleTagDeclDefinition(TagDecl * D)1987330f729Sjoerg   void HandleTagDeclDefinition(TagDecl *D) override {
1997330f729Sjoerg     if (Diags.hasErrorOccurred())
2007330f729Sjoerg       return;
2017330f729Sjoerg 
2027330f729Sjoerg     if (D->isFromASTFile())
2037330f729Sjoerg       return;
2047330f729Sjoerg 
2057330f729Sjoerg     // Anonymous tag decls are deferred until we are building their declcontext.
2067330f729Sjoerg     if (D->getName().empty())
2077330f729Sjoerg       return;
2087330f729Sjoerg 
2097330f729Sjoerg     // Defer tag decls until their declcontext is complete.
2107330f729Sjoerg     auto *DeclCtx = D->getDeclContext();
2117330f729Sjoerg     while (DeclCtx) {
2127330f729Sjoerg       if (auto *D = dyn_cast<TagDecl>(DeclCtx))
2137330f729Sjoerg         if (!D->isCompleteDefinition())
2147330f729Sjoerg           return;
2157330f729Sjoerg       DeclCtx = DeclCtx->getParent();
2167330f729Sjoerg     }
2177330f729Sjoerg 
2187330f729Sjoerg     DebugTypeVisitor DTV(*Builder->getModuleDebugInfo(), *Ctx);
2197330f729Sjoerg     DTV.TraverseDecl(D);
2207330f729Sjoerg     Builder->UpdateCompletedType(D);
2217330f729Sjoerg   }
2227330f729Sjoerg 
HandleTagDeclRequiredDefinition(const TagDecl * D)2237330f729Sjoerg   void HandleTagDeclRequiredDefinition(const TagDecl *D) override {
2247330f729Sjoerg     if (Diags.hasErrorOccurred())
2257330f729Sjoerg       return;
2267330f729Sjoerg 
2277330f729Sjoerg     if (const RecordDecl *RD = dyn_cast<RecordDecl>(D))
2287330f729Sjoerg       Builder->getModuleDebugInfo()->completeRequiredType(RD);
2297330f729Sjoerg   }
2307330f729Sjoerg 
HandleImplicitImportDecl(ImportDecl * D)2317330f729Sjoerg   void HandleImplicitImportDecl(ImportDecl *D) override {
2327330f729Sjoerg     if (!D->getImportedOwningModule())
2337330f729Sjoerg       Builder->getModuleDebugInfo()->EmitImportDecl(*D);
2347330f729Sjoerg   }
2357330f729Sjoerg 
2367330f729Sjoerg   /// Emit a container holding the serialized AST.
HandleTranslationUnit(ASTContext & Ctx)2377330f729Sjoerg   void HandleTranslationUnit(ASTContext &Ctx) override {
2387330f729Sjoerg     assert(M && VMContext && Builder);
2397330f729Sjoerg     // Delete these on function exit.
2407330f729Sjoerg     std::unique_ptr<llvm::LLVMContext> VMContext = std::move(this->VMContext);
2417330f729Sjoerg     std::unique_ptr<llvm::Module> M = std::move(this->M);
2427330f729Sjoerg     std::unique_ptr<CodeGen::CodeGenModule> Builder = std::move(this->Builder);
2437330f729Sjoerg 
2447330f729Sjoerg     if (Diags.hasErrorOccurred())
2457330f729Sjoerg       return;
2467330f729Sjoerg 
2477330f729Sjoerg     M->setTargetTriple(Ctx.getTargetInfo().getTriple().getTriple());
248*e038c9c4Sjoerg     M->setDataLayout(Ctx.getTargetInfo().getDataLayoutString());
2497330f729Sjoerg 
2507330f729Sjoerg     // PCH files don't have a signature field in the control block,
2517330f729Sjoerg     // but LLVM detects DWO CUs by looking for a non-zero DWO id.
2527330f729Sjoerg     // We use the lower 64 bits for debug info.
253*e038c9c4Sjoerg 
2547330f729Sjoerg     uint64_t Signature =
255*e038c9c4Sjoerg         Buffer->Signature ? Buffer->Signature.truncatedValue() : ~1ULL;
256*e038c9c4Sjoerg 
2577330f729Sjoerg     Builder->getModuleDebugInfo()->setDwoId(Signature);
2587330f729Sjoerg 
2597330f729Sjoerg     // Finalize the Builder.
2607330f729Sjoerg     if (Builder)
2617330f729Sjoerg       Builder->Release();
2627330f729Sjoerg 
2637330f729Sjoerg     // Ensure the target exists.
2647330f729Sjoerg     std::string Error;
2657330f729Sjoerg     auto Triple = Ctx.getTargetInfo().getTriple();
2667330f729Sjoerg     if (!llvm::TargetRegistry::lookupTarget(Triple.getTriple(), Error))
2677330f729Sjoerg       llvm::report_fatal_error(Error);
2687330f729Sjoerg 
2697330f729Sjoerg     // Emit the serialized Clang AST into its own section.
2707330f729Sjoerg     assert(Buffer->IsComplete && "serialization did not complete");
2717330f729Sjoerg     auto &SerializedAST = Buffer->Data;
2727330f729Sjoerg     auto Size = SerializedAST.size();
2737330f729Sjoerg     auto Int8Ty = llvm::Type::getInt8Ty(*VMContext);
2747330f729Sjoerg     auto *Ty = llvm::ArrayType::get(Int8Ty, Size);
2757330f729Sjoerg     auto *Data = llvm::ConstantDataArray::getString(
2767330f729Sjoerg         *VMContext, StringRef(SerializedAST.data(), Size),
2777330f729Sjoerg         /*AddNull=*/false);
2787330f729Sjoerg     auto *ASTSym = new llvm::GlobalVariable(
2797330f729Sjoerg         *M, Ty, /*constant*/ true, llvm::GlobalVariable::InternalLinkage, Data,
2807330f729Sjoerg         "__clang_ast");
2817330f729Sjoerg     // The on-disk hashtable needs to be aligned.
2827330f729Sjoerg     ASTSym->setAlignment(llvm::Align(8));
2837330f729Sjoerg 
2847330f729Sjoerg     // Mach-O also needs a segment name.
2857330f729Sjoerg     if (Triple.isOSBinFormatMachO())
2867330f729Sjoerg       ASTSym->setSection("__CLANG,__clangast");
2877330f729Sjoerg     // COFF has an eight character length limit.
2887330f729Sjoerg     else if (Triple.isOSBinFormatCOFF())
2897330f729Sjoerg       ASTSym->setSection("clangast");
2907330f729Sjoerg     else
2917330f729Sjoerg       ASTSym->setSection("__clangast");
2927330f729Sjoerg 
2937330f729Sjoerg     LLVM_DEBUG({
2947330f729Sjoerg       // Print the IR for the PCH container to the debug output.
2957330f729Sjoerg       llvm::SmallString<0> Buffer;
2967330f729Sjoerg       clang::EmitBackendOutput(
2977330f729Sjoerg           Diags, HeaderSearchOpts, CodeGenOpts, TargetOpts, LangOpts,
298*e038c9c4Sjoerg           Ctx.getTargetInfo().getDataLayoutString(), M.get(),
2997330f729Sjoerg           BackendAction::Backend_EmitLL,
3007330f729Sjoerg           std::make_unique<llvm::raw_svector_ostream>(Buffer));
3017330f729Sjoerg       llvm::dbgs() << Buffer;
3027330f729Sjoerg     });
3037330f729Sjoerg 
3047330f729Sjoerg     // Use the LLVM backend to emit the pch container.
3057330f729Sjoerg     clang::EmitBackendOutput(Diags, HeaderSearchOpts, CodeGenOpts, TargetOpts,
306*e038c9c4Sjoerg                              LangOpts,
307*e038c9c4Sjoerg                              Ctx.getTargetInfo().getDataLayoutString(), M.get(),
308*e038c9c4Sjoerg                              BackendAction::Backend_EmitObj, std::move(OS));
3097330f729Sjoerg 
3107330f729Sjoerg     // Free the memory for the temporary buffer.
3117330f729Sjoerg     llvm::SmallVector<char, 0> Empty;
3127330f729Sjoerg     SerializedAST = std::move(Empty);
3137330f729Sjoerg   }
3147330f729Sjoerg };
3157330f729Sjoerg 
3167330f729Sjoerg } // anonymous namespace
3177330f729Sjoerg 
3187330f729Sjoerg 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) const3197330f729Sjoerg ObjectFilePCHContainerWriter::CreatePCHContainerGenerator(
3207330f729Sjoerg     CompilerInstance &CI, const std::string &MainFileName,
3217330f729Sjoerg     const std::string &OutputFileName,
3227330f729Sjoerg     std::unique_ptr<llvm::raw_pwrite_stream> OS,
3237330f729Sjoerg     std::shared_ptr<PCHBuffer> Buffer) const {
3247330f729Sjoerg   return std::make_unique<PCHContainerGenerator>(
3257330f729Sjoerg       CI, MainFileName, OutputFileName, std::move(OS), Buffer);
3267330f729Sjoerg }
3277330f729Sjoerg 
3287330f729Sjoerg StringRef
ExtractPCH(llvm::MemoryBufferRef Buffer) const3297330f729Sjoerg ObjectFilePCHContainerReader::ExtractPCH(llvm::MemoryBufferRef Buffer) const {
3307330f729Sjoerg   StringRef PCH;
3317330f729Sjoerg   auto OFOrErr = llvm::object::ObjectFile::createObjectFile(Buffer);
3327330f729Sjoerg   if (OFOrErr) {
3337330f729Sjoerg     auto &OF = OFOrErr.get();
3347330f729Sjoerg     bool IsCOFF = isa<llvm::object::COFFObjectFile>(*OF);
3357330f729Sjoerg     // Find the clang AST section in the container.
3367330f729Sjoerg     for (auto &Section : OF->sections()) {
3377330f729Sjoerg       StringRef Name;
3387330f729Sjoerg       if (Expected<StringRef> NameOrErr = Section.getName())
3397330f729Sjoerg         Name = *NameOrErr;
3407330f729Sjoerg       else
3417330f729Sjoerg         consumeError(NameOrErr.takeError());
3427330f729Sjoerg 
3437330f729Sjoerg       if ((!IsCOFF && Name == "__clangast") || (IsCOFF && Name == "clangast")) {
3447330f729Sjoerg         if (Expected<StringRef> E = Section.getContents())
3457330f729Sjoerg           return *E;
3467330f729Sjoerg         else {
3477330f729Sjoerg           handleAllErrors(E.takeError(), [&](const llvm::ErrorInfoBase &EIB) {
3487330f729Sjoerg             EIB.log(llvm::errs());
3497330f729Sjoerg           });
3507330f729Sjoerg           return "";
3517330f729Sjoerg         }
3527330f729Sjoerg       }
3537330f729Sjoerg     }
3547330f729Sjoerg   }
3557330f729Sjoerg   handleAllErrors(OFOrErr.takeError(), [&](const llvm::ErrorInfoBase &EIB) {
3567330f729Sjoerg     if (EIB.convertToErrorCode() ==
3577330f729Sjoerg         llvm::object::object_error::invalid_file_type)
3587330f729Sjoerg       // As a fallback, treat the buffer as a raw AST.
3597330f729Sjoerg       PCH = Buffer.getBuffer();
3607330f729Sjoerg     else
3617330f729Sjoerg       EIB.log(llvm::errs());
3627330f729Sjoerg   });
3637330f729Sjoerg   return PCH;
3647330f729Sjoerg }
365