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" 30349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h" 31*0b57cec5SDimitry Andric #include "llvm/Object/COFF.h" 32*0b57cec5SDimitry Andric #include "llvm/Object/ObjectFile.h" 33*0b57cec5SDimitry Andric #include "llvm/Support/Path.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; 52e8d8bef9SDimitry Andric 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"; 150e8d8bef9SDimitry Andric LangOpts.setThreadModel(LangOptions::ThreadModelKind::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; 15904eeddc0SDimitry Andric CodeGenOpts.DebugStrictDwarf = CI.getCodeGenOpts().DebugStrictDwarf; 160*0b57cec5SDimitry Andric } 161*0b57cec5SDimitry Andric 162*0b57cec5SDimitry Andric ~PCHContainerGenerator() override = default; 163*0b57cec5SDimitry Andric 164*0b57cec5SDimitry Andric void Initialize(ASTContext &Context) override { 165*0b57cec5SDimitry Andric assert(!Ctx && "initialized multiple times"); 166*0b57cec5SDimitry Andric 167*0b57cec5SDimitry Andric Ctx = &Context; 168*0b57cec5SDimitry Andric VMContext.reset(new llvm::LLVMContext()); 169*0b57cec5SDimitry Andric M.reset(new llvm::Module(MainFileName, *VMContext)); 170fe6060f1SDimitry Andric M->setDataLayout(Ctx->getTargetInfo().getDataLayoutString()); 171*0b57cec5SDimitry Andric Builder.reset(new CodeGen::CodeGenModule( 172*0b57cec5SDimitry Andric *Ctx, HeaderSearchOpts, PreprocessorOpts, CodeGenOpts, *M, Diags)); 173*0b57cec5SDimitry Andric 174*0b57cec5SDimitry Andric // Prepare CGDebugInfo to emit debug info for a clang module. 175*0b57cec5SDimitry Andric auto *DI = Builder->getModuleDebugInfo(); 176*0b57cec5SDimitry Andric StringRef ModuleName = llvm::sys::path::filename(MainFileName); 1775ffd83dbSDimitry Andric DI->setPCHDescriptor( 1785ffd83dbSDimitry Andric {ModuleName, "", OutputFileName, ASTFileSignature::createDISentinel()}); 179*0b57cec5SDimitry Andric DI->setModuleMap(MMap); 180*0b57cec5SDimitry Andric } 181*0b57cec5SDimitry Andric 182*0b57cec5SDimitry Andric bool HandleTopLevelDecl(DeclGroupRef D) override { 183*0b57cec5SDimitry Andric if (Diags.hasErrorOccurred()) 184*0b57cec5SDimitry Andric return true; 185*0b57cec5SDimitry Andric 186*0b57cec5SDimitry Andric // Collect debug info for all decls in this group. 187*0b57cec5SDimitry Andric for (auto *I : D) 188*0b57cec5SDimitry Andric if (!I->isFromASTFile()) { 189*0b57cec5SDimitry Andric DebugTypeVisitor DTV(*Builder->getModuleDebugInfo(), *Ctx); 190*0b57cec5SDimitry Andric DTV.TraverseDecl(I); 191*0b57cec5SDimitry Andric } 192*0b57cec5SDimitry Andric return true; 193*0b57cec5SDimitry Andric } 194*0b57cec5SDimitry Andric 195*0b57cec5SDimitry Andric void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override { 196*0b57cec5SDimitry Andric HandleTopLevelDecl(D); 197*0b57cec5SDimitry Andric } 198*0b57cec5SDimitry Andric 199*0b57cec5SDimitry Andric void HandleTagDeclDefinition(TagDecl *D) override { 200*0b57cec5SDimitry Andric if (Diags.hasErrorOccurred()) 201*0b57cec5SDimitry Andric return; 202*0b57cec5SDimitry Andric 203*0b57cec5SDimitry Andric if (D->isFromASTFile()) 204*0b57cec5SDimitry Andric return; 205*0b57cec5SDimitry Andric 206*0b57cec5SDimitry Andric // Anonymous tag decls are deferred until we are building their declcontext. 207*0b57cec5SDimitry Andric if (D->getName().empty()) 208*0b57cec5SDimitry Andric return; 209*0b57cec5SDimitry Andric 210*0b57cec5SDimitry Andric // Defer tag decls until their declcontext is complete. 211*0b57cec5SDimitry Andric auto *DeclCtx = D->getDeclContext(); 212*0b57cec5SDimitry Andric while (DeclCtx) { 213*0b57cec5SDimitry Andric if (auto *D = dyn_cast<TagDecl>(DeclCtx)) 214*0b57cec5SDimitry Andric if (!D->isCompleteDefinition()) 215*0b57cec5SDimitry Andric return; 216*0b57cec5SDimitry Andric DeclCtx = DeclCtx->getParent(); 217*0b57cec5SDimitry Andric } 218*0b57cec5SDimitry Andric 219*0b57cec5SDimitry Andric DebugTypeVisitor DTV(*Builder->getModuleDebugInfo(), *Ctx); 220*0b57cec5SDimitry Andric DTV.TraverseDecl(D); 221*0b57cec5SDimitry Andric Builder->UpdateCompletedType(D); 222*0b57cec5SDimitry Andric } 223*0b57cec5SDimitry Andric 224*0b57cec5SDimitry Andric void HandleTagDeclRequiredDefinition(const TagDecl *D) override { 225*0b57cec5SDimitry Andric if (Diags.hasErrorOccurred()) 226*0b57cec5SDimitry Andric return; 227*0b57cec5SDimitry Andric 228*0b57cec5SDimitry Andric if (const RecordDecl *RD = dyn_cast<RecordDecl>(D)) 229*0b57cec5SDimitry Andric Builder->getModuleDebugInfo()->completeRequiredType(RD); 230*0b57cec5SDimitry Andric } 231*0b57cec5SDimitry Andric 232*0b57cec5SDimitry Andric void HandleImplicitImportDecl(ImportDecl *D) override { 233*0b57cec5SDimitry Andric if (!D->getImportedOwningModule()) 234*0b57cec5SDimitry Andric Builder->getModuleDebugInfo()->EmitImportDecl(*D); 235*0b57cec5SDimitry Andric } 236*0b57cec5SDimitry Andric 237*0b57cec5SDimitry Andric /// Emit a container holding the serialized AST. 238*0b57cec5SDimitry Andric void HandleTranslationUnit(ASTContext &Ctx) override { 239*0b57cec5SDimitry Andric assert(M && VMContext && Builder); 240*0b57cec5SDimitry Andric // Delete these on function exit. 241*0b57cec5SDimitry Andric std::unique_ptr<llvm::LLVMContext> VMContext = std::move(this->VMContext); 242*0b57cec5SDimitry Andric std::unique_ptr<llvm::Module> M = std::move(this->M); 243*0b57cec5SDimitry Andric std::unique_ptr<CodeGen::CodeGenModule> Builder = std::move(this->Builder); 244*0b57cec5SDimitry Andric 245*0b57cec5SDimitry Andric if (Diags.hasErrorOccurred()) 246*0b57cec5SDimitry Andric return; 247*0b57cec5SDimitry Andric 248*0b57cec5SDimitry Andric M->setTargetTriple(Ctx.getTargetInfo().getTriple().getTriple()); 249fe6060f1SDimitry Andric M->setDataLayout(Ctx.getTargetInfo().getDataLayoutString()); 250*0b57cec5SDimitry Andric 251*0b57cec5SDimitry Andric // PCH files don't have a signature field in the control block, 252*0b57cec5SDimitry Andric // but LLVM detects DWO CUs by looking for a non-zero DWO id. 253*0b57cec5SDimitry Andric // We use the lower 64 bits for debug info. 254e8d8bef9SDimitry Andric 255*0b57cec5SDimitry Andric uint64_t Signature = 256e8d8bef9SDimitry Andric Buffer->Signature ? Buffer->Signature.truncatedValue() : ~1ULL; 257e8d8bef9SDimitry Andric 258*0b57cec5SDimitry Andric Builder->getModuleDebugInfo()->setDwoId(Signature); 259*0b57cec5SDimitry Andric 260*0b57cec5SDimitry Andric // Finalize the Builder. 261*0b57cec5SDimitry Andric if (Builder) 262*0b57cec5SDimitry Andric Builder->Release(); 263*0b57cec5SDimitry Andric 264*0b57cec5SDimitry Andric // Ensure the target exists. 265*0b57cec5SDimitry Andric std::string Error; 266*0b57cec5SDimitry Andric auto Triple = Ctx.getTargetInfo().getTriple(); 267*0b57cec5SDimitry Andric if (!llvm::TargetRegistry::lookupTarget(Triple.getTriple(), Error)) 268349cc55cSDimitry Andric llvm::report_fatal_error(llvm::Twine(Error)); 269*0b57cec5SDimitry Andric 270*0b57cec5SDimitry Andric // Emit the serialized Clang AST into its own section. 271*0b57cec5SDimitry Andric assert(Buffer->IsComplete && "serialization did not complete"); 272*0b57cec5SDimitry Andric auto &SerializedAST = Buffer->Data; 273*0b57cec5SDimitry Andric auto Size = SerializedAST.size(); 274349cc55cSDimitry Andric 275349cc55cSDimitry Andric if (Triple.isOSBinFormatWasm()) { 276349cc55cSDimitry Andric // Emit __clangast in custom section instead of named data segment 277349cc55cSDimitry Andric // to find it while iterating sections. 278349cc55cSDimitry Andric // This could be avoided if all data segements (the wasm sense) were 279349cc55cSDimitry Andric // represented as their own sections (in the llvm sense). 280349cc55cSDimitry Andric // TODO: https://github.com/WebAssembly/tool-conventions/issues/138 281349cc55cSDimitry Andric llvm::NamedMDNode *MD = 282349cc55cSDimitry Andric M->getOrInsertNamedMetadata("wasm.custom_sections"); 283349cc55cSDimitry Andric llvm::Metadata *Ops[2] = { 284349cc55cSDimitry Andric llvm::MDString::get(*VMContext, "__clangast"), 285349cc55cSDimitry Andric llvm::MDString::get(*VMContext, 286349cc55cSDimitry Andric StringRef(SerializedAST.data(), Size))}; 287349cc55cSDimitry Andric auto *NameAndContent = llvm::MDTuple::get(*VMContext, Ops); 288349cc55cSDimitry Andric MD->addOperand(NameAndContent); 289349cc55cSDimitry Andric } else { 290*0b57cec5SDimitry Andric auto Int8Ty = llvm::Type::getInt8Ty(*VMContext); 291*0b57cec5SDimitry Andric auto *Ty = llvm::ArrayType::get(Int8Ty, Size); 292*0b57cec5SDimitry Andric auto *Data = llvm::ConstantDataArray::getString( 293*0b57cec5SDimitry Andric *VMContext, StringRef(SerializedAST.data(), Size), 294*0b57cec5SDimitry Andric /*AddNull=*/false); 295*0b57cec5SDimitry Andric auto *ASTSym = new llvm::GlobalVariable( 296349cc55cSDimitry Andric *M, Ty, /*constant*/ true, llvm::GlobalVariable::InternalLinkage, 297349cc55cSDimitry Andric Data, "__clang_ast"); 298*0b57cec5SDimitry Andric // The on-disk hashtable needs to be aligned. 299a7dea167SDimitry Andric ASTSym->setAlignment(llvm::Align(8)); 300*0b57cec5SDimitry Andric 301*0b57cec5SDimitry Andric // Mach-O also needs a segment name. 302*0b57cec5SDimitry Andric if (Triple.isOSBinFormatMachO()) 303*0b57cec5SDimitry Andric ASTSym->setSection("__CLANG,__clangast"); 304*0b57cec5SDimitry Andric // COFF has an eight character length limit. 305*0b57cec5SDimitry Andric else if (Triple.isOSBinFormatCOFF()) 306*0b57cec5SDimitry Andric ASTSym->setSection("clangast"); 307*0b57cec5SDimitry Andric else 308*0b57cec5SDimitry Andric ASTSym->setSection("__clangast"); 309349cc55cSDimitry Andric } 310*0b57cec5SDimitry Andric 311*0b57cec5SDimitry Andric LLVM_DEBUG({ 312*0b57cec5SDimitry Andric // Print the IR for the PCH container to the debug output. 313*0b57cec5SDimitry Andric llvm::SmallString<0> Buffer; 314*0b57cec5SDimitry Andric clang::EmitBackendOutput( 315*0b57cec5SDimitry Andric Diags, HeaderSearchOpts, CodeGenOpts, TargetOpts, LangOpts, 316fe6060f1SDimitry Andric Ctx.getTargetInfo().getDataLayoutString(), M.get(), 317*0b57cec5SDimitry Andric BackendAction::Backend_EmitLL, 318a7dea167SDimitry Andric std::make_unique<llvm::raw_svector_ostream>(Buffer)); 319*0b57cec5SDimitry Andric llvm::dbgs() << Buffer; 320*0b57cec5SDimitry Andric }); 321*0b57cec5SDimitry Andric 322*0b57cec5SDimitry Andric // Use the LLVM backend to emit the pch container. 323*0b57cec5SDimitry Andric clang::EmitBackendOutput(Diags, HeaderSearchOpts, CodeGenOpts, TargetOpts, 324fe6060f1SDimitry Andric LangOpts, 325fe6060f1SDimitry Andric Ctx.getTargetInfo().getDataLayoutString(), M.get(), 326fe6060f1SDimitry Andric BackendAction::Backend_EmitObj, std::move(OS)); 327*0b57cec5SDimitry Andric 328*0b57cec5SDimitry Andric // Free the memory for the temporary buffer. 329*0b57cec5SDimitry Andric llvm::SmallVector<char, 0> Empty; 330*0b57cec5SDimitry Andric SerializedAST = std::move(Empty); 331*0b57cec5SDimitry Andric } 332*0b57cec5SDimitry Andric }; 333*0b57cec5SDimitry Andric 334*0b57cec5SDimitry Andric } // anonymous namespace 335*0b57cec5SDimitry Andric 336*0b57cec5SDimitry Andric std::unique_ptr<ASTConsumer> 337*0b57cec5SDimitry Andric ObjectFilePCHContainerWriter::CreatePCHContainerGenerator( 338*0b57cec5SDimitry Andric CompilerInstance &CI, const std::string &MainFileName, 339*0b57cec5SDimitry Andric const std::string &OutputFileName, 340*0b57cec5SDimitry Andric std::unique_ptr<llvm::raw_pwrite_stream> OS, 341*0b57cec5SDimitry Andric std::shared_ptr<PCHBuffer> Buffer) const { 342a7dea167SDimitry Andric return std::make_unique<PCHContainerGenerator>( 343*0b57cec5SDimitry Andric CI, MainFileName, OutputFileName, std::move(OS), Buffer); 344*0b57cec5SDimitry Andric } 345*0b57cec5SDimitry Andric 346*0b57cec5SDimitry Andric StringRef 347*0b57cec5SDimitry Andric ObjectFilePCHContainerReader::ExtractPCH(llvm::MemoryBufferRef Buffer) const { 348*0b57cec5SDimitry Andric StringRef PCH; 349*0b57cec5SDimitry Andric auto OFOrErr = llvm::object::ObjectFile::createObjectFile(Buffer); 350*0b57cec5SDimitry Andric if (OFOrErr) { 351*0b57cec5SDimitry Andric auto &OF = OFOrErr.get(); 352*0b57cec5SDimitry Andric bool IsCOFF = isa<llvm::object::COFFObjectFile>(*OF); 353*0b57cec5SDimitry Andric // Find the clang AST section in the container. 354*0b57cec5SDimitry Andric for (auto &Section : OF->sections()) { 355*0b57cec5SDimitry Andric StringRef Name; 356a7dea167SDimitry Andric if (Expected<StringRef> NameOrErr = Section.getName()) 357a7dea167SDimitry Andric Name = *NameOrErr; 358a7dea167SDimitry Andric else 359a7dea167SDimitry Andric consumeError(NameOrErr.takeError()); 360a7dea167SDimitry Andric 361*0b57cec5SDimitry Andric if ((!IsCOFF && Name == "__clangast") || (IsCOFF && Name == "clangast")) { 362*0b57cec5SDimitry Andric if (Expected<StringRef> E = Section.getContents()) 363*0b57cec5SDimitry Andric return *E; 364*0b57cec5SDimitry Andric else { 365*0b57cec5SDimitry Andric handleAllErrors(E.takeError(), [&](const llvm::ErrorInfoBase &EIB) { 366*0b57cec5SDimitry Andric EIB.log(llvm::errs()); 367*0b57cec5SDimitry Andric }); 368*0b57cec5SDimitry Andric return ""; 369*0b57cec5SDimitry Andric } 370*0b57cec5SDimitry Andric } 371*0b57cec5SDimitry Andric } 372*0b57cec5SDimitry Andric } 373*0b57cec5SDimitry Andric handleAllErrors(OFOrErr.takeError(), [&](const llvm::ErrorInfoBase &EIB) { 374*0b57cec5SDimitry Andric if (EIB.convertToErrorCode() == 375*0b57cec5SDimitry Andric llvm::object::object_error::invalid_file_type) 376*0b57cec5SDimitry Andric // As a fallback, treat the buffer as a raw AST. 377*0b57cec5SDimitry Andric PCH = Buffer.getBuffer(); 378*0b57cec5SDimitry Andric else 379*0b57cec5SDimitry Andric EIB.log(llvm::errs()); 380*0b57cec5SDimitry Andric }); 381*0b57cec5SDimitry Andric return PCH; 382*0b57cec5SDimitry Andric } 383