10b57cec5SDimitry Andric //===--- ObjectFilePCHContainerOperations.cpp -----------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "clang/CodeGen/ObjectFilePCHContainerOperations.h" 100b57cec5SDimitry Andric #include "CGDebugInfo.h" 110b57cec5SDimitry Andric #include "CodeGenModule.h" 120b57cec5SDimitry Andric #include "clang/AST/ASTContext.h" 130b57cec5SDimitry Andric #include "clang/AST/DeclObjC.h" 140b57cec5SDimitry Andric #include "clang/AST/Expr.h" 150b57cec5SDimitry Andric #include "clang/AST/RecursiveASTVisitor.h" 160b57cec5SDimitry Andric #include "clang/Basic/CodeGenOptions.h" 170b57cec5SDimitry Andric #include "clang/Basic/Diagnostic.h" 180b57cec5SDimitry Andric #include "clang/Basic/TargetInfo.h" 190b57cec5SDimitry Andric #include "clang/CodeGen/BackendUtil.h" 200b57cec5SDimitry Andric #include "clang/Frontend/CompilerInstance.h" 210b57cec5SDimitry Andric #include "clang/Lex/HeaderSearch.h" 220b57cec5SDimitry Andric #include "clang/Lex/Preprocessor.h" 230b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 240b57cec5SDimitry Andric #include "llvm/Bitstream/BitstreamReader.h" 250b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFContext.h" 260b57cec5SDimitry Andric #include "llvm/IR/Constants.h" 270b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h" 280b57cec5SDimitry Andric #include "llvm/IR/LLVMContext.h" 290b57cec5SDimitry Andric #include "llvm/IR/Module.h" 30349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h" 310b57cec5SDimitry Andric #include "llvm/Object/COFF.h" 320b57cec5SDimitry Andric #include "llvm/Object/ObjectFile.h" 330b57cec5SDimitry Andric #include "llvm/Support/Path.h" 340b57cec5SDimitry Andric #include <memory> 350b57cec5SDimitry Andric #include <utility> 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric using namespace clang; 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric #define DEBUG_TYPE "pchcontainer" 400b57cec5SDimitry Andric 410b57cec5SDimitry Andric namespace { 420b57cec5SDimitry Andric class PCHContainerGenerator : public ASTConsumer { 430b57cec5SDimitry Andric DiagnosticsEngine &Diags; 440b57cec5SDimitry Andric const std::string MainFileName; 450b57cec5SDimitry Andric const std::string OutputFileName; 460b57cec5SDimitry Andric ASTContext *Ctx; 470b57cec5SDimitry Andric ModuleMap &MMap; 48972a253aSDimitry Andric IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS; 490b57cec5SDimitry Andric const HeaderSearchOptions &HeaderSearchOpts; 500b57cec5SDimitry Andric const PreprocessorOptions &PreprocessorOpts; 510b57cec5SDimitry Andric CodeGenOptions CodeGenOpts; 520b57cec5SDimitry Andric const TargetOptions TargetOpts; 53e8d8bef9SDimitry Andric LangOptions LangOpts; 540b57cec5SDimitry Andric std::unique_ptr<llvm::LLVMContext> VMContext; 550b57cec5SDimitry Andric std::unique_ptr<llvm::Module> M; 560b57cec5SDimitry Andric std::unique_ptr<CodeGen::CodeGenModule> Builder; 570b57cec5SDimitry Andric std::unique_ptr<raw_pwrite_stream> OS; 580b57cec5SDimitry Andric std::shared_ptr<PCHBuffer> Buffer; 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric /// Visit every type and emit debug info for it. 610b57cec5SDimitry Andric struct DebugTypeVisitor : public RecursiveASTVisitor<DebugTypeVisitor> { 620b57cec5SDimitry Andric clang::CodeGen::CGDebugInfo &DI; 630b57cec5SDimitry Andric ASTContext &Ctx; 640b57cec5SDimitry Andric DebugTypeVisitor(clang::CodeGen::CGDebugInfo &DI, ASTContext &Ctx) 650b57cec5SDimitry Andric : DI(DI), Ctx(Ctx) {} 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric /// Determine whether this type can be represented in DWARF. 680b57cec5SDimitry Andric static bool CanRepresent(const Type *Ty) { 690b57cec5SDimitry Andric return !Ty->isDependentType() && !Ty->isUndeducedType(); 700b57cec5SDimitry Andric } 710b57cec5SDimitry Andric 720b57cec5SDimitry Andric bool VisitImportDecl(ImportDecl *D) { 730b57cec5SDimitry Andric if (!D->getImportedOwningModule()) 740b57cec5SDimitry Andric DI.EmitImportDecl(*D); 750b57cec5SDimitry Andric return true; 760b57cec5SDimitry Andric } 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric bool VisitTypeDecl(TypeDecl *D) { 790b57cec5SDimitry Andric // TagDecls may be deferred until after all decls have been merged and we 800b57cec5SDimitry Andric // know the complete type. Pure forward declarations will be skipped, but 810b57cec5SDimitry Andric // they don't need to be emitted into the module anyway. 820b57cec5SDimitry Andric if (auto *TD = dyn_cast<TagDecl>(D)) 830b57cec5SDimitry Andric if (!TD->isCompleteDefinition()) 840b57cec5SDimitry Andric return true; 850b57cec5SDimitry Andric 860b57cec5SDimitry Andric QualType QualTy = Ctx.getTypeDeclType(D); 870b57cec5SDimitry Andric if (!QualTy.isNull() && CanRepresent(QualTy.getTypePtr())) 880b57cec5SDimitry Andric DI.getOrCreateStandaloneType(QualTy, D->getLocation()); 890b57cec5SDimitry Andric return true; 900b57cec5SDimitry Andric } 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { 930b57cec5SDimitry Andric QualType QualTy(D->getTypeForDecl(), 0); 940b57cec5SDimitry Andric if (!QualTy.isNull() && CanRepresent(QualTy.getTypePtr())) 950b57cec5SDimitry Andric DI.getOrCreateStandaloneType(QualTy, D->getLocation()); 960b57cec5SDimitry Andric return true; 970b57cec5SDimitry Andric } 980b57cec5SDimitry Andric 990b57cec5SDimitry Andric bool VisitFunctionDecl(FunctionDecl *D) { 10081ad6265SDimitry Andric // Skip deduction guides. 10181ad6265SDimitry Andric if (isa<CXXDeductionGuideDecl>(D)) 10281ad6265SDimitry Andric return true; 10381ad6265SDimitry Andric 1040b57cec5SDimitry Andric if (isa<CXXMethodDecl>(D)) 1050b57cec5SDimitry Andric // This is not yet supported. Constructing the `this' argument 1060b57cec5SDimitry Andric // mandates a CodeGenFunction. 1070b57cec5SDimitry Andric return true; 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric SmallVector<QualType, 16> ArgTypes; 110bdd1243dSDimitry Andric for (auto *i : D->parameters()) 1110b57cec5SDimitry Andric ArgTypes.push_back(i->getType()); 1120b57cec5SDimitry Andric QualType RetTy = D->getReturnType(); 1130b57cec5SDimitry Andric QualType FnTy = Ctx.getFunctionType(RetTy, ArgTypes, 1140b57cec5SDimitry Andric FunctionProtoType::ExtProtoInfo()); 1150b57cec5SDimitry Andric if (CanRepresent(FnTy.getTypePtr())) 1160b57cec5SDimitry Andric DI.EmitFunctionDecl(D, D->getLocation(), FnTy); 1170b57cec5SDimitry Andric return true; 1180b57cec5SDimitry Andric } 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric bool VisitObjCMethodDecl(ObjCMethodDecl *D) { 1210b57cec5SDimitry Andric if (!D->getClassInterface()) 1220b57cec5SDimitry Andric return true; 1230b57cec5SDimitry Andric 1240b57cec5SDimitry Andric bool selfIsPseudoStrong, selfIsConsumed; 1250b57cec5SDimitry Andric SmallVector<QualType, 16> ArgTypes; 1260b57cec5SDimitry Andric ArgTypes.push_back(D->getSelfType(Ctx, D->getClassInterface(), 1270b57cec5SDimitry Andric selfIsPseudoStrong, selfIsConsumed)); 1280b57cec5SDimitry Andric ArgTypes.push_back(Ctx.getObjCSelType()); 129bdd1243dSDimitry Andric for (auto *i : D->parameters()) 1300b57cec5SDimitry Andric ArgTypes.push_back(i->getType()); 1310b57cec5SDimitry Andric QualType RetTy = D->getReturnType(); 1320b57cec5SDimitry Andric QualType FnTy = Ctx.getFunctionType(RetTy, ArgTypes, 1330b57cec5SDimitry Andric FunctionProtoType::ExtProtoInfo()); 1340b57cec5SDimitry Andric if (CanRepresent(FnTy.getTypePtr())) 1350b57cec5SDimitry Andric DI.EmitFunctionDecl(D, D->getLocation(), FnTy); 1360b57cec5SDimitry Andric return true; 1370b57cec5SDimitry Andric } 1380b57cec5SDimitry Andric }; 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric public: 1410b57cec5SDimitry Andric PCHContainerGenerator(CompilerInstance &CI, const std::string &MainFileName, 1420b57cec5SDimitry Andric const std::string &OutputFileName, 1430b57cec5SDimitry Andric std::unique_ptr<raw_pwrite_stream> OS, 1440b57cec5SDimitry Andric std::shared_ptr<PCHBuffer> Buffer) 1450b57cec5SDimitry Andric : Diags(CI.getDiagnostics()), MainFileName(MainFileName), 1460b57cec5SDimitry Andric OutputFileName(OutputFileName), Ctx(nullptr), 1470b57cec5SDimitry Andric MMap(CI.getPreprocessor().getHeaderSearchInfo().getModuleMap()), 148972a253aSDimitry Andric FS(&CI.getVirtualFileSystem()), 1490b57cec5SDimitry Andric HeaderSearchOpts(CI.getHeaderSearchOpts()), 1500b57cec5SDimitry Andric PreprocessorOpts(CI.getPreprocessorOpts()), 1510b57cec5SDimitry Andric TargetOpts(CI.getTargetOpts()), LangOpts(CI.getLangOpts()), 1520b57cec5SDimitry Andric OS(std::move(OS)), Buffer(std::move(Buffer)) { 1530b57cec5SDimitry Andric // The debug info output isn't affected by CodeModel and 1540b57cec5SDimitry Andric // ThreadModel, but the backend expects them to be nonempty. 1550b57cec5SDimitry Andric CodeGenOpts.CodeModel = "default"; 156e8d8bef9SDimitry Andric LangOpts.setThreadModel(LangOptions::ThreadModelKind::Single); 1570b57cec5SDimitry Andric CodeGenOpts.DebugTypeExtRefs = true; 1580b57cec5SDimitry Andric // When building a module MainFileName is the name of the modulemap file. 1590b57cec5SDimitry Andric CodeGenOpts.MainFileName = 1600b57cec5SDimitry Andric LangOpts.CurrentModule.empty() ? MainFileName : LangOpts.CurrentModule; 161*fe013be4SDimitry Andric CodeGenOpts.setDebugInfo(llvm::codegenoptions::FullDebugInfo); 1620b57cec5SDimitry Andric CodeGenOpts.setDebuggerTuning(CI.getCodeGenOpts().getDebuggerTuning()); 1630b57cec5SDimitry Andric CodeGenOpts.DebugPrefixMap = 1640b57cec5SDimitry Andric CI.getInvocation().getCodeGenOpts().DebugPrefixMap; 16504eeddc0SDimitry Andric CodeGenOpts.DebugStrictDwarf = CI.getCodeGenOpts().DebugStrictDwarf; 1660b57cec5SDimitry Andric } 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric ~PCHContainerGenerator() override = default; 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric void Initialize(ASTContext &Context) override { 1710b57cec5SDimitry Andric assert(!Ctx && "initialized multiple times"); 1720b57cec5SDimitry Andric 1730b57cec5SDimitry Andric Ctx = &Context; 1740b57cec5SDimitry Andric VMContext.reset(new llvm::LLVMContext()); 1750b57cec5SDimitry Andric M.reset(new llvm::Module(MainFileName, *VMContext)); 176fe6060f1SDimitry Andric M->setDataLayout(Ctx->getTargetInfo().getDataLayoutString()); 1770b57cec5SDimitry Andric Builder.reset(new CodeGen::CodeGenModule( 178972a253aSDimitry Andric *Ctx, FS, HeaderSearchOpts, PreprocessorOpts, CodeGenOpts, *M, Diags)); 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric // Prepare CGDebugInfo to emit debug info for a clang module. 1810b57cec5SDimitry Andric auto *DI = Builder->getModuleDebugInfo(); 1820b57cec5SDimitry Andric StringRef ModuleName = llvm::sys::path::filename(MainFileName); 1835ffd83dbSDimitry Andric DI->setPCHDescriptor( 1845ffd83dbSDimitry Andric {ModuleName, "", OutputFileName, ASTFileSignature::createDISentinel()}); 1850b57cec5SDimitry Andric DI->setModuleMap(MMap); 1860b57cec5SDimitry Andric } 1870b57cec5SDimitry Andric 1880b57cec5SDimitry Andric bool HandleTopLevelDecl(DeclGroupRef D) override { 1890b57cec5SDimitry Andric if (Diags.hasErrorOccurred()) 1900b57cec5SDimitry Andric return true; 1910b57cec5SDimitry Andric 1920b57cec5SDimitry Andric // Collect debug info for all decls in this group. 1930b57cec5SDimitry Andric for (auto *I : D) 1940b57cec5SDimitry Andric if (!I->isFromASTFile()) { 1950b57cec5SDimitry Andric DebugTypeVisitor DTV(*Builder->getModuleDebugInfo(), *Ctx); 1960b57cec5SDimitry Andric DTV.TraverseDecl(I); 1970b57cec5SDimitry Andric } 1980b57cec5SDimitry Andric return true; 1990b57cec5SDimitry Andric } 2000b57cec5SDimitry Andric 2010b57cec5SDimitry Andric void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override { 2020b57cec5SDimitry Andric HandleTopLevelDecl(D); 2030b57cec5SDimitry Andric } 2040b57cec5SDimitry Andric 2050b57cec5SDimitry Andric void HandleTagDeclDefinition(TagDecl *D) override { 2060b57cec5SDimitry Andric if (Diags.hasErrorOccurred()) 2070b57cec5SDimitry Andric return; 2080b57cec5SDimitry Andric 2090b57cec5SDimitry Andric if (D->isFromASTFile()) 2100b57cec5SDimitry Andric return; 2110b57cec5SDimitry Andric 2120b57cec5SDimitry Andric // Anonymous tag decls are deferred until we are building their declcontext. 2130b57cec5SDimitry Andric if (D->getName().empty()) 2140b57cec5SDimitry Andric return; 2150b57cec5SDimitry Andric 2160b57cec5SDimitry Andric // Defer tag decls until their declcontext is complete. 2170b57cec5SDimitry Andric auto *DeclCtx = D->getDeclContext(); 2180b57cec5SDimitry Andric while (DeclCtx) { 2190b57cec5SDimitry Andric if (auto *D = dyn_cast<TagDecl>(DeclCtx)) 2200b57cec5SDimitry Andric if (!D->isCompleteDefinition()) 2210b57cec5SDimitry Andric return; 2220b57cec5SDimitry Andric DeclCtx = DeclCtx->getParent(); 2230b57cec5SDimitry Andric } 2240b57cec5SDimitry Andric 2250b57cec5SDimitry Andric DebugTypeVisitor DTV(*Builder->getModuleDebugInfo(), *Ctx); 2260b57cec5SDimitry Andric DTV.TraverseDecl(D); 2270b57cec5SDimitry Andric Builder->UpdateCompletedType(D); 2280b57cec5SDimitry Andric } 2290b57cec5SDimitry Andric 2300b57cec5SDimitry Andric void HandleTagDeclRequiredDefinition(const TagDecl *D) override { 2310b57cec5SDimitry Andric if (Diags.hasErrorOccurred()) 2320b57cec5SDimitry Andric return; 2330b57cec5SDimitry Andric 2340b57cec5SDimitry Andric if (const RecordDecl *RD = dyn_cast<RecordDecl>(D)) 2350b57cec5SDimitry Andric Builder->getModuleDebugInfo()->completeRequiredType(RD); 2360b57cec5SDimitry Andric } 2370b57cec5SDimitry Andric 2380b57cec5SDimitry Andric void HandleImplicitImportDecl(ImportDecl *D) override { 2390b57cec5SDimitry Andric if (!D->getImportedOwningModule()) 2400b57cec5SDimitry Andric Builder->getModuleDebugInfo()->EmitImportDecl(*D); 2410b57cec5SDimitry Andric } 2420b57cec5SDimitry Andric 2430b57cec5SDimitry Andric /// Emit a container holding the serialized AST. 2440b57cec5SDimitry Andric void HandleTranslationUnit(ASTContext &Ctx) override { 2450b57cec5SDimitry Andric assert(M && VMContext && Builder); 2460b57cec5SDimitry Andric // Delete these on function exit. 2470b57cec5SDimitry Andric std::unique_ptr<llvm::LLVMContext> VMContext = std::move(this->VMContext); 2480b57cec5SDimitry Andric std::unique_ptr<llvm::Module> M = std::move(this->M); 2490b57cec5SDimitry Andric std::unique_ptr<CodeGen::CodeGenModule> Builder = std::move(this->Builder); 2500b57cec5SDimitry Andric 2510b57cec5SDimitry Andric if (Diags.hasErrorOccurred()) 2520b57cec5SDimitry Andric return; 2530b57cec5SDimitry Andric 2540b57cec5SDimitry Andric M->setTargetTriple(Ctx.getTargetInfo().getTriple().getTriple()); 255fe6060f1SDimitry Andric M->setDataLayout(Ctx.getTargetInfo().getDataLayoutString()); 2560b57cec5SDimitry Andric 2570b57cec5SDimitry Andric // PCH files don't have a signature field in the control block, 2580b57cec5SDimitry Andric // but LLVM detects DWO CUs by looking for a non-zero DWO id. 2590b57cec5SDimitry Andric // We use the lower 64 bits for debug info. 260e8d8bef9SDimitry Andric 2610b57cec5SDimitry Andric uint64_t Signature = 262e8d8bef9SDimitry Andric Buffer->Signature ? Buffer->Signature.truncatedValue() : ~1ULL; 263e8d8bef9SDimitry Andric 2640b57cec5SDimitry Andric Builder->getModuleDebugInfo()->setDwoId(Signature); 2650b57cec5SDimitry Andric 2660b57cec5SDimitry Andric // Finalize the Builder. 2670b57cec5SDimitry Andric if (Builder) 2680b57cec5SDimitry Andric Builder->Release(); 2690b57cec5SDimitry Andric 2700b57cec5SDimitry Andric // Ensure the target exists. 2710b57cec5SDimitry Andric std::string Error; 2720b57cec5SDimitry Andric auto Triple = Ctx.getTargetInfo().getTriple(); 2730b57cec5SDimitry Andric if (!llvm::TargetRegistry::lookupTarget(Triple.getTriple(), Error)) 274349cc55cSDimitry Andric llvm::report_fatal_error(llvm::Twine(Error)); 2750b57cec5SDimitry Andric 2760b57cec5SDimitry Andric // Emit the serialized Clang AST into its own section. 2770b57cec5SDimitry Andric assert(Buffer->IsComplete && "serialization did not complete"); 2780b57cec5SDimitry Andric auto &SerializedAST = Buffer->Data; 2790b57cec5SDimitry Andric auto Size = SerializedAST.size(); 280349cc55cSDimitry Andric 281349cc55cSDimitry Andric if (Triple.isOSBinFormatWasm()) { 282349cc55cSDimitry Andric // Emit __clangast in custom section instead of named data segment 283349cc55cSDimitry Andric // to find it while iterating sections. 284349cc55cSDimitry Andric // This could be avoided if all data segements (the wasm sense) were 285349cc55cSDimitry Andric // represented as their own sections (in the llvm sense). 286349cc55cSDimitry Andric // TODO: https://github.com/WebAssembly/tool-conventions/issues/138 287349cc55cSDimitry Andric llvm::NamedMDNode *MD = 288349cc55cSDimitry Andric M->getOrInsertNamedMetadata("wasm.custom_sections"); 289349cc55cSDimitry Andric llvm::Metadata *Ops[2] = { 290349cc55cSDimitry Andric llvm::MDString::get(*VMContext, "__clangast"), 291349cc55cSDimitry Andric llvm::MDString::get(*VMContext, 292349cc55cSDimitry Andric StringRef(SerializedAST.data(), Size))}; 293349cc55cSDimitry Andric auto *NameAndContent = llvm::MDTuple::get(*VMContext, Ops); 294349cc55cSDimitry Andric MD->addOperand(NameAndContent); 295349cc55cSDimitry Andric } else { 2960b57cec5SDimitry Andric auto Int8Ty = llvm::Type::getInt8Ty(*VMContext); 2970b57cec5SDimitry Andric auto *Ty = llvm::ArrayType::get(Int8Ty, Size); 2980b57cec5SDimitry Andric auto *Data = llvm::ConstantDataArray::getString( 2990b57cec5SDimitry Andric *VMContext, StringRef(SerializedAST.data(), Size), 3000b57cec5SDimitry Andric /*AddNull=*/false); 3010b57cec5SDimitry Andric auto *ASTSym = new llvm::GlobalVariable( 302349cc55cSDimitry Andric *M, Ty, /*constant*/ true, llvm::GlobalVariable::InternalLinkage, 303349cc55cSDimitry Andric Data, "__clang_ast"); 3040b57cec5SDimitry Andric // The on-disk hashtable needs to be aligned. 305a7dea167SDimitry Andric ASTSym->setAlignment(llvm::Align(8)); 3060b57cec5SDimitry Andric 3070b57cec5SDimitry Andric // Mach-O also needs a segment name. 3080b57cec5SDimitry Andric if (Triple.isOSBinFormatMachO()) 3090b57cec5SDimitry Andric ASTSym->setSection("__CLANG,__clangast"); 3100b57cec5SDimitry Andric // COFF has an eight character length limit. 3110b57cec5SDimitry Andric else if (Triple.isOSBinFormatCOFF()) 3120b57cec5SDimitry Andric ASTSym->setSection("clangast"); 3130b57cec5SDimitry Andric else 3140b57cec5SDimitry Andric ASTSym->setSection("__clangast"); 315349cc55cSDimitry Andric } 3160b57cec5SDimitry Andric 3170b57cec5SDimitry Andric LLVM_DEBUG({ 3180b57cec5SDimitry Andric // Print the IR for the PCH container to the debug output. 3190b57cec5SDimitry Andric llvm::SmallString<0> Buffer; 3200b57cec5SDimitry Andric clang::EmitBackendOutput( 3210b57cec5SDimitry Andric Diags, HeaderSearchOpts, CodeGenOpts, TargetOpts, LangOpts, 322fe6060f1SDimitry Andric Ctx.getTargetInfo().getDataLayoutString(), M.get(), 323*fe013be4SDimitry Andric BackendAction::Backend_EmitLL, FS, 324a7dea167SDimitry Andric std::make_unique<llvm::raw_svector_ostream>(Buffer)); 3250b57cec5SDimitry Andric llvm::dbgs() << Buffer; 3260b57cec5SDimitry Andric }); 3270b57cec5SDimitry Andric 3280b57cec5SDimitry Andric // Use the LLVM backend to emit the pch container. 3290b57cec5SDimitry Andric clang::EmitBackendOutput(Diags, HeaderSearchOpts, CodeGenOpts, TargetOpts, 330fe6060f1SDimitry Andric LangOpts, 331fe6060f1SDimitry Andric Ctx.getTargetInfo().getDataLayoutString(), M.get(), 332*fe013be4SDimitry Andric BackendAction::Backend_EmitObj, FS, std::move(OS)); 3330b57cec5SDimitry Andric 3340b57cec5SDimitry Andric // Free the memory for the temporary buffer. 3350b57cec5SDimitry Andric llvm::SmallVector<char, 0> Empty; 3360b57cec5SDimitry Andric SerializedAST = std::move(Empty); 3370b57cec5SDimitry Andric } 3380b57cec5SDimitry Andric }; 3390b57cec5SDimitry Andric 3400b57cec5SDimitry Andric } // anonymous namespace 3410b57cec5SDimitry Andric 3420b57cec5SDimitry Andric std::unique_ptr<ASTConsumer> 3430b57cec5SDimitry Andric ObjectFilePCHContainerWriter::CreatePCHContainerGenerator( 3440b57cec5SDimitry Andric CompilerInstance &CI, const std::string &MainFileName, 3450b57cec5SDimitry Andric const std::string &OutputFileName, 3460b57cec5SDimitry Andric std::unique_ptr<llvm::raw_pwrite_stream> OS, 3470b57cec5SDimitry Andric std::shared_ptr<PCHBuffer> Buffer) const { 348a7dea167SDimitry Andric return std::make_unique<PCHContainerGenerator>( 3490b57cec5SDimitry Andric CI, MainFileName, OutputFileName, std::move(OS), Buffer); 3500b57cec5SDimitry Andric } 3510b57cec5SDimitry Andric 352*fe013be4SDimitry Andric ArrayRef<StringRef> ObjectFilePCHContainerReader::getFormats() const { 353*fe013be4SDimitry Andric static StringRef Formats[] = {"obj", "raw"}; 354*fe013be4SDimitry Andric return Formats; 355*fe013be4SDimitry Andric } 356*fe013be4SDimitry Andric 3570b57cec5SDimitry Andric StringRef 3580b57cec5SDimitry Andric ObjectFilePCHContainerReader::ExtractPCH(llvm::MemoryBufferRef Buffer) const { 3590b57cec5SDimitry Andric StringRef PCH; 3600b57cec5SDimitry Andric auto OFOrErr = llvm::object::ObjectFile::createObjectFile(Buffer); 3610b57cec5SDimitry Andric if (OFOrErr) { 3620b57cec5SDimitry Andric auto &OF = OFOrErr.get(); 3630b57cec5SDimitry Andric bool IsCOFF = isa<llvm::object::COFFObjectFile>(*OF); 3640b57cec5SDimitry Andric // Find the clang AST section in the container. 3650b57cec5SDimitry Andric for (auto &Section : OF->sections()) { 3660b57cec5SDimitry Andric StringRef Name; 367a7dea167SDimitry Andric if (Expected<StringRef> NameOrErr = Section.getName()) 368a7dea167SDimitry Andric Name = *NameOrErr; 369a7dea167SDimitry Andric else 370a7dea167SDimitry Andric consumeError(NameOrErr.takeError()); 371a7dea167SDimitry Andric 3720b57cec5SDimitry Andric if ((!IsCOFF && Name == "__clangast") || (IsCOFF && Name == "clangast")) { 3730b57cec5SDimitry Andric if (Expected<StringRef> E = Section.getContents()) 3740b57cec5SDimitry Andric return *E; 3750b57cec5SDimitry Andric else { 3760b57cec5SDimitry Andric handleAllErrors(E.takeError(), [&](const llvm::ErrorInfoBase &EIB) { 3770b57cec5SDimitry Andric EIB.log(llvm::errs()); 3780b57cec5SDimitry Andric }); 3790b57cec5SDimitry Andric return ""; 3800b57cec5SDimitry Andric } 3810b57cec5SDimitry Andric } 3820b57cec5SDimitry Andric } 3830b57cec5SDimitry Andric } 3840b57cec5SDimitry Andric handleAllErrors(OFOrErr.takeError(), [&](const llvm::ErrorInfoBase &EIB) { 3850b57cec5SDimitry Andric if (EIB.convertToErrorCode() == 3860b57cec5SDimitry Andric llvm::object::object_error::invalid_file_type) 3870b57cec5SDimitry Andric // As a fallback, treat the buffer as a raw AST. 3880b57cec5SDimitry Andric PCH = Buffer.getBuffer(); 3890b57cec5SDimitry Andric else 3900b57cec5SDimitry Andric EIB.log(llvm::errs()); 3910b57cec5SDimitry Andric }); 3920b57cec5SDimitry Andric return PCH; 3930b57cec5SDimitry Andric } 394