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