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