1d64eccf4SChuanqi Xu //===--- ObjectFilePCHContainerWriter.cpp -----------------------------===// 2d64eccf4SChuanqi Xu // 3d64eccf4SChuanqi Xu // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4d64eccf4SChuanqi Xu // See https://llvm.org/LICENSE.txt for license information. 5d64eccf4SChuanqi Xu // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6d64eccf4SChuanqi Xu // 7d64eccf4SChuanqi Xu //===----------------------------------------------------------------------===// 8d64eccf4SChuanqi Xu 9d64eccf4SChuanqi Xu #include "clang/CodeGen/ObjectFilePCHContainerWriter.h" 10d64eccf4SChuanqi Xu #include "CGDebugInfo.h" 11d64eccf4SChuanqi Xu #include "CodeGenModule.h" 12d64eccf4SChuanqi Xu #include "clang/AST/ASTContext.h" 13d64eccf4SChuanqi Xu #include "clang/AST/DeclObjC.h" 14d64eccf4SChuanqi Xu #include "clang/AST/Expr.h" 15d64eccf4SChuanqi Xu #include "clang/AST/RecursiveASTVisitor.h" 16d64eccf4SChuanqi Xu #include "clang/Basic/CodeGenOptions.h" 17d64eccf4SChuanqi Xu #include "clang/Basic/Diagnostic.h" 18d64eccf4SChuanqi Xu #include "clang/Basic/TargetInfo.h" 19d64eccf4SChuanqi Xu #include "clang/CodeGen/BackendUtil.h" 20d64eccf4SChuanqi Xu #include "clang/Frontend/CompilerInstance.h" 21d64eccf4SChuanqi Xu #include "clang/Lex/HeaderSearch.h" 22d64eccf4SChuanqi Xu #include "clang/Lex/Preprocessor.h" 23d64eccf4SChuanqi Xu #include "llvm/ADT/StringRef.h" 24d64eccf4SChuanqi Xu #include "llvm/IR/Constants.h" 25d64eccf4SChuanqi Xu #include "llvm/IR/DataLayout.h" 26d64eccf4SChuanqi Xu #include "llvm/IR/LLVMContext.h" 27d64eccf4SChuanqi Xu #include "llvm/IR/Module.h" 28d64eccf4SChuanqi Xu #include "llvm/MC/TargetRegistry.h" 29d64eccf4SChuanqi Xu #include "llvm/Object/COFF.h" 30d64eccf4SChuanqi Xu #include "llvm/Support/Path.h" 31d64eccf4SChuanqi Xu #include <memory> 32d64eccf4SChuanqi Xu #include <utility> 33d64eccf4SChuanqi Xu 34d64eccf4SChuanqi Xu using namespace clang; 35d64eccf4SChuanqi Xu 36d64eccf4SChuanqi Xu #define DEBUG_TYPE "pchcontainer" 37d64eccf4SChuanqi Xu 38d64eccf4SChuanqi Xu namespace { 39d64eccf4SChuanqi Xu class PCHContainerGenerator : public ASTConsumer { 4048d0eb51SFangrui Song CompilerInstance &CI; 41d64eccf4SChuanqi Xu DiagnosticsEngine &Diags; 42d64eccf4SChuanqi Xu const std::string MainFileName; 43d64eccf4SChuanqi Xu const std::string OutputFileName; 44d64eccf4SChuanqi Xu ASTContext *Ctx; 45d64eccf4SChuanqi Xu ModuleMap &MMap; 46d64eccf4SChuanqi Xu IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS; 47d64eccf4SChuanqi Xu const HeaderSearchOptions &HeaderSearchOpts; 48d64eccf4SChuanqi Xu const PreprocessorOptions &PreprocessorOpts; 49d64eccf4SChuanqi Xu CodeGenOptions CodeGenOpts; 50d64eccf4SChuanqi Xu const TargetOptions TargetOpts; 51d64eccf4SChuanqi Xu LangOptions LangOpts; 52d64eccf4SChuanqi Xu std::unique_ptr<llvm::LLVMContext> VMContext; 53d64eccf4SChuanqi Xu std::unique_ptr<llvm::Module> M; 54d64eccf4SChuanqi Xu std::unique_ptr<CodeGen::CodeGenModule> Builder; 55d64eccf4SChuanqi Xu std::unique_ptr<raw_pwrite_stream> OS; 56d64eccf4SChuanqi Xu std::shared_ptr<PCHBuffer> Buffer; 57d64eccf4SChuanqi Xu 58d64eccf4SChuanqi Xu /// Visit every type and emit debug info for it. 59d64eccf4SChuanqi Xu struct DebugTypeVisitor : public RecursiveASTVisitor<DebugTypeVisitor> { 60d64eccf4SChuanqi Xu clang::CodeGen::CGDebugInfo &DI; 61d64eccf4SChuanqi Xu ASTContext &Ctx; 62d64eccf4SChuanqi Xu DebugTypeVisitor(clang::CodeGen::CGDebugInfo &DI, ASTContext &Ctx) 63d64eccf4SChuanqi Xu : DI(DI), Ctx(Ctx) {} 64d64eccf4SChuanqi Xu 65d64eccf4SChuanqi Xu /// Determine whether this type can be represented in DWARF. 66d64eccf4SChuanqi Xu static bool CanRepresent(const Type *Ty) { 67d64eccf4SChuanqi Xu return !Ty->isDependentType() && !Ty->isUndeducedType(); 68d64eccf4SChuanqi Xu } 69d64eccf4SChuanqi Xu 70d64eccf4SChuanqi Xu bool VisitImportDecl(ImportDecl *D) { 71d64eccf4SChuanqi Xu if (!D->getImportedOwningModule()) 72d64eccf4SChuanqi Xu DI.EmitImportDecl(*D); 73d64eccf4SChuanqi Xu return true; 74d64eccf4SChuanqi Xu } 75d64eccf4SChuanqi Xu 76d64eccf4SChuanqi Xu bool VisitTypeDecl(TypeDecl *D) { 77d64eccf4SChuanqi Xu // TagDecls may be deferred until after all decls have been merged and we 78d64eccf4SChuanqi Xu // know the complete type. Pure forward declarations will be skipped, but 79d64eccf4SChuanqi Xu // they don't need to be emitted into the module anyway. 80d64eccf4SChuanqi Xu if (auto *TD = dyn_cast<TagDecl>(D)) 81d64eccf4SChuanqi Xu if (!TD->isCompleteDefinition()) 82d64eccf4SChuanqi Xu return true; 83d64eccf4SChuanqi Xu 8430e276d0SMichael Buch if (D->hasAttr<NoDebugAttr>()) 8530e276d0SMichael Buch return true; 8630e276d0SMichael Buch 87d64eccf4SChuanqi Xu QualType QualTy = Ctx.getTypeDeclType(D); 88d64eccf4SChuanqi Xu if (!QualTy.isNull() && CanRepresent(QualTy.getTypePtr())) 89d64eccf4SChuanqi Xu DI.getOrCreateStandaloneType(QualTy, D->getLocation()); 90d64eccf4SChuanqi Xu return true; 91d64eccf4SChuanqi Xu } 92d64eccf4SChuanqi Xu 93d64eccf4SChuanqi Xu bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { 94d64eccf4SChuanqi Xu QualType QualTy(D->getTypeForDecl(), 0); 95d64eccf4SChuanqi Xu if (!QualTy.isNull() && CanRepresent(QualTy.getTypePtr())) 96d64eccf4SChuanqi Xu DI.getOrCreateStandaloneType(QualTy, D->getLocation()); 97d64eccf4SChuanqi Xu return true; 98d64eccf4SChuanqi Xu } 99d64eccf4SChuanqi Xu 100d64eccf4SChuanqi Xu bool VisitFunctionDecl(FunctionDecl *D) { 101d64eccf4SChuanqi Xu // Skip deduction guides. 102d64eccf4SChuanqi Xu if (isa<CXXDeductionGuideDecl>(D)) 103d64eccf4SChuanqi Xu return true; 104d64eccf4SChuanqi Xu 105d64eccf4SChuanqi Xu if (isa<CXXMethodDecl>(D)) 106d64eccf4SChuanqi Xu // This is not yet supported. Constructing the `this' argument 107d64eccf4SChuanqi Xu // mandates a CodeGenFunction. 108d64eccf4SChuanqi Xu return true; 109d64eccf4SChuanqi Xu 110d64eccf4SChuanqi Xu SmallVector<QualType, 16> ArgTypes; 111d64eccf4SChuanqi Xu for (auto *i : D->parameters()) 112d64eccf4SChuanqi Xu ArgTypes.push_back(i->getType()); 113d64eccf4SChuanqi Xu QualType RetTy = D->getReturnType(); 114d64eccf4SChuanqi Xu QualType FnTy = Ctx.getFunctionType(RetTy, ArgTypes, 115d64eccf4SChuanqi Xu FunctionProtoType::ExtProtoInfo()); 116d64eccf4SChuanqi Xu if (CanRepresent(FnTy.getTypePtr())) 117d64eccf4SChuanqi Xu DI.EmitFunctionDecl(D, D->getLocation(), FnTy); 118d64eccf4SChuanqi Xu return true; 119d64eccf4SChuanqi Xu } 120d64eccf4SChuanqi Xu 121d64eccf4SChuanqi Xu bool VisitObjCMethodDecl(ObjCMethodDecl *D) { 122d64eccf4SChuanqi Xu if (!D->getClassInterface()) 123d64eccf4SChuanqi Xu return true; 124d64eccf4SChuanqi Xu 125d64eccf4SChuanqi Xu bool selfIsPseudoStrong, selfIsConsumed; 126d64eccf4SChuanqi Xu SmallVector<QualType, 16> ArgTypes; 127d64eccf4SChuanqi Xu ArgTypes.push_back(D->getSelfType(Ctx, D->getClassInterface(), 128d64eccf4SChuanqi Xu selfIsPseudoStrong, selfIsConsumed)); 129d64eccf4SChuanqi Xu ArgTypes.push_back(Ctx.getObjCSelType()); 130d64eccf4SChuanqi Xu for (auto *i : D->parameters()) 131d64eccf4SChuanqi Xu ArgTypes.push_back(i->getType()); 132d64eccf4SChuanqi Xu QualType RetTy = D->getReturnType(); 133d64eccf4SChuanqi Xu QualType FnTy = Ctx.getFunctionType(RetTy, ArgTypes, 134d64eccf4SChuanqi Xu FunctionProtoType::ExtProtoInfo()); 135d64eccf4SChuanqi Xu if (CanRepresent(FnTy.getTypePtr())) 136d64eccf4SChuanqi Xu DI.EmitFunctionDecl(D, D->getLocation(), FnTy); 137d64eccf4SChuanqi Xu return true; 138d64eccf4SChuanqi Xu } 139d64eccf4SChuanqi Xu }; 140d64eccf4SChuanqi Xu 141d64eccf4SChuanqi Xu public: 142d64eccf4SChuanqi Xu PCHContainerGenerator(CompilerInstance &CI, const std::string &MainFileName, 143d64eccf4SChuanqi Xu const std::string &OutputFileName, 144d64eccf4SChuanqi Xu std::unique_ptr<raw_pwrite_stream> OS, 145d64eccf4SChuanqi Xu std::shared_ptr<PCHBuffer> Buffer) 14648d0eb51SFangrui Song : CI(CI), Diags(CI.getDiagnostics()), MainFileName(MainFileName), 147d64eccf4SChuanqi Xu OutputFileName(OutputFileName), Ctx(nullptr), 148d64eccf4SChuanqi Xu MMap(CI.getPreprocessor().getHeaderSearchInfo().getModuleMap()), 149d64eccf4SChuanqi Xu FS(&CI.getVirtualFileSystem()), 150d64eccf4SChuanqi Xu HeaderSearchOpts(CI.getHeaderSearchOpts()), 151d64eccf4SChuanqi Xu PreprocessorOpts(CI.getPreprocessorOpts()), 152d64eccf4SChuanqi Xu TargetOpts(CI.getTargetOpts()), LangOpts(CI.getLangOpts()), 153d64eccf4SChuanqi Xu OS(std::move(OS)), Buffer(std::move(Buffer)) { 154d64eccf4SChuanqi Xu // The debug info output isn't affected by CodeModel and 155d64eccf4SChuanqi Xu // ThreadModel, but the backend expects them to be nonempty. 156d64eccf4SChuanqi Xu CodeGenOpts.CodeModel = "default"; 157d64eccf4SChuanqi Xu LangOpts.setThreadModel(LangOptions::ThreadModelKind::Single); 158d64eccf4SChuanqi Xu CodeGenOpts.DebugTypeExtRefs = true; 159d64eccf4SChuanqi Xu // When building a module MainFileName is the name of the modulemap file. 160d64eccf4SChuanqi Xu CodeGenOpts.MainFileName = 161d64eccf4SChuanqi Xu LangOpts.CurrentModule.empty() ? MainFileName : LangOpts.CurrentModule; 162d64eccf4SChuanqi Xu CodeGenOpts.setDebugInfo(llvm::codegenoptions::FullDebugInfo); 163d64eccf4SChuanqi Xu CodeGenOpts.setDebuggerTuning(CI.getCodeGenOpts().getDebuggerTuning()); 164d64eccf4SChuanqi Xu CodeGenOpts.DwarfVersion = CI.getCodeGenOpts().DwarfVersion; 165d64eccf4SChuanqi Xu CodeGenOpts.DebugCompilationDir = 166d64eccf4SChuanqi Xu CI.getInvocation().getCodeGenOpts().DebugCompilationDir; 167d64eccf4SChuanqi Xu CodeGenOpts.DebugPrefixMap = 168d64eccf4SChuanqi Xu CI.getInvocation().getCodeGenOpts().DebugPrefixMap; 169d64eccf4SChuanqi Xu CodeGenOpts.DebugStrictDwarf = CI.getCodeGenOpts().DebugStrictDwarf; 170d64eccf4SChuanqi Xu } 171d64eccf4SChuanqi Xu 172d64eccf4SChuanqi Xu ~PCHContainerGenerator() override = default; 173d64eccf4SChuanqi Xu 174d64eccf4SChuanqi Xu void Initialize(ASTContext &Context) override { 175d64eccf4SChuanqi Xu assert(!Ctx && "initialized multiple times"); 176d64eccf4SChuanqi Xu 177d64eccf4SChuanqi Xu Ctx = &Context; 178d64eccf4SChuanqi Xu VMContext.reset(new llvm::LLVMContext()); 179d64eccf4SChuanqi Xu M.reset(new llvm::Module(MainFileName, *VMContext)); 180d64eccf4SChuanqi Xu M->setDataLayout(Ctx->getTargetInfo().getDataLayoutString()); 181d64eccf4SChuanqi Xu Builder.reset(new CodeGen::CodeGenModule( 182d64eccf4SChuanqi Xu *Ctx, FS, HeaderSearchOpts, PreprocessorOpts, CodeGenOpts, *M, Diags)); 183d64eccf4SChuanqi Xu 184d64eccf4SChuanqi Xu // Prepare CGDebugInfo to emit debug info for a clang module. 185d64eccf4SChuanqi Xu auto *DI = Builder->getModuleDebugInfo(); 186d64eccf4SChuanqi Xu StringRef ModuleName = llvm::sys::path::filename(MainFileName); 187d64eccf4SChuanqi Xu DI->setPCHDescriptor( 188d64eccf4SChuanqi Xu {ModuleName, "", OutputFileName, ASTFileSignature::createDISentinel()}); 189d64eccf4SChuanqi Xu DI->setModuleMap(MMap); 190d64eccf4SChuanqi Xu } 191d64eccf4SChuanqi Xu 192d64eccf4SChuanqi Xu bool HandleTopLevelDecl(DeclGroupRef D) override { 193d64eccf4SChuanqi Xu if (Diags.hasErrorOccurred()) 194d64eccf4SChuanqi Xu return true; 195d64eccf4SChuanqi Xu 196d64eccf4SChuanqi Xu // Collect debug info for all decls in this group. 197d64eccf4SChuanqi Xu for (auto *I : D) 198d64eccf4SChuanqi Xu if (!I->isFromASTFile()) { 199d64eccf4SChuanqi Xu DebugTypeVisitor DTV(*Builder->getModuleDebugInfo(), *Ctx); 200d64eccf4SChuanqi Xu DTV.TraverseDecl(I); 201d64eccf4SChuanqi Xu } 202d64eccf4SChuanqi Xu return true; 203d64eccf4SChuanqi Xu } 204d64eccf4SChuanqi Xu 205d64eccf4SChuanqi Xu void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override { 206d64eccf4SChuanqi Xu HandleTopLevelDecl(D); 207d64eccf4SChuanqi Xu } 208d64eccf4SChuanqi Xu 209d64eccf4SChuanqi Xu void HandleTagDeclDefinition(TagDecl *D) override { 210d64eccf4SChuanqi Xu if (Diags.hasErrorOccurred()) 211d64eccf4SChuanqi Xu return; 212d64eccf4SChuanqi Xu 213d64eccf4SChuanqi Xu if (D->isFromASTFile()) 214d64eccf4SChuanqi Xu return; 215d64eccf4SChuanqi Xu 216d64eccf4SChuanqi Xu // Anonymous tag decls are deferred until we are building their declcontext. 217d64eccf4SChuanqi Xu if (D->getName().empty()) 218d64eccf4SChuanqi Xu return; 219d64eccf4SChuanqi Xu 220d64eccf4SChuanqi Xu // Defer tag decls until their declcontext is complete. 221d64eccf4SChuanqi Xu auto *DeclCtx = D->getDeclContext(); 222d64eccf4SChuanqi Xu while (DeclCtx) { 223d64eccf4SChuanqi Xu if (auto *D = dyn_cast<TagDecl>(DeclCtx)) 224d64eccf4SChuanqi Xu if (!D->isCompleteDefinition()) 225d64eccf4SChuanqi Xu return; 226d64eccf4SChuanqi Xu DeclCtx = DeclCtx->getParent(); 227d64eccf4SChuanqi Xu } 228d64eccf4SChuanqi Xu 229d64eccf4SChuanqi Xu DebugTypeVisitor DTV(*Builder->getModuleDebugInfo(), *Ctx); 230d64eccf4SChuanqi Xu DTV.TraverseDecl(D); 231d64eccf4SChuanqi Xu Builder->UpdateCompletedType(D); 232d64eccf4SChuanqi Xu } 233d64eccf4SChuanqi Xu 234d64eccf4SChuanqi Xu void HandleTagDeclRequiredDefinition(const TagDecl *D) override { 235d64eccf4SChuanqi Xu if (Diags.hasErrorOccurred()) 236d64eccf4SChuanqi Xu return; 237d64eccf4SChuanqi Xu 238d64eccf4SChuanqi Xu if (const RecordDecl *RD = dyn_cast<RecordDecl>(D)) 239d64eccf4SChuanqi Xu Builder->getModuleDebugInfo()->completeRequiredType(RD); 240d64eccf4SChuanqi Xu } 241d64eccf4SChuanqi Xu 242d64eccf4SChuanqi Xu void HandleImplicitImportDecl(ImportDecl *D) override { 243d64eccf4SChuanqi Xu if (!D->getImportedOwningModule()) 244d64eccf4SChuanqi Xu Builder->getModuleDebugInfo()->EmitImportDecl(*D); 245d64eccf4SChuanqi Xu } 246d64eccf4SChuanqi Xu 247d64eccf4SChuanqi Xu /// Emit a container holding the serialized AST. 248d64eccf4SChuanqi Xu void HandleTranslationUnit(ASTContext &Ctx) override { 249d64eccf4SChuanqi Xu assert(M && VMContext && Builder); 250d64eccf4SChuanqi Xu // Delete these on function exit. 251d64eccf4SChuanqi Xu std::unique_ptr<llvm::LLVMContext> VMContext = std::move(this->VMContext); 252d64eccf4SChuanqi Xu std::unique_ptr<llvm::Module> M = std::move(this->M); 253d64eccf4SChuanqi Xu std::unique_ptr<CodeGen::CodeGenModule> Builder = std::move(this->Builder); 254d64eccf4SChuanqi Xu 255d64eccf4SChuanqi Xu if (Diags.hasErrorOccurred()) 256d64eccf4SChuanqi Xu return; 257d64eccf4SChuanqi Xu 258d64eccf4SChuanqi Xu M->setTargetTriple(Ctx.getTargetInfo().getTriple().getTriple()); 259d64eccf4SChuanqi Xu M->setDataLayout(Ctx.getTargetInfo().getDataLayoutString()); 260d64eccf4SChuanqi Xu 261d64eccf4SChuanqi Xu // PCH files don't have a signature field in the control block, 262d64eccf4SChuanqi Xu // but LLVM detects DWO CUs by looking for a non-zero DWO id. 263d64eccf4SChuanqi Xu // We use the lower 64 bits for debug info. 264d64eccf4SChuanqi Xu 265d64eccf4SChuanqi Xu uint64_t Signature = 266d64eccf4SChuanqi Xu Buffer->Signature ? Buffer->Signature.truncatedValue() : ~1ULL; 267d64eccf4SChuanqi Xu 268d64eccf4SChuanqi Xu Builder->getModuleDebugInfo()->setDwoId(Signature); 269d64eccf4SChuanqi Xu 270d64eccf4SChuanqi Xu // Finalize the Builder. 271d64eccf4SChuanqi Xu if (Builder) 272d64eccf4SChuanqi Xu Builder->Release(); 273d64eccf4SChuanqi Xu 274d64eccf4SChuanqi Xu // Ensure the target exists. 275d64eccf4SChuanqi Xu std::string Error; 276d64eccf4SChuanqi Xu auto Triple = Ctx.getTargetInfo().getTriple(); 277d64eccf4SChuanqi Xu if (!llvm::TargetRegistry::lookupTarget(Triple.getTriple(), Error)) 278d64eccf4SChuanqi Xu llvm::report_fatal_error(llvm::Twine(Error)); 279d64eccf4SChuanqi Xu 280d64eccf4SChuanqi Xu // Emit the serialized Clang AST into its own section. 281d64eccf4SChuanqi Xu assert(Buffer->IsComplete && "serialization did not complete"); 282d64eccf4SChuanqi Xu auto &SerializedAST = Buffer->Data; 283d64eccf4SChuanqi Xu auto Size = SerializedAST.size(); 284d64eccf4SChuanqi Xu 285d64eccf4SChuanqi Xu if (Triple.isOSBinFormatWasm()) { 286d64eccf4SChuanqi Xu // Emit __clangast in custom section instead of named data segment 287d64eccf4SChuanqi Xu // to find it while iterating sections. 288d64eccf4SChuanqi Xu // This could be avoided if all data segements (the wasm sense) were 289d64eccf4SChuanqi Xu // represented as their own sections (in the llvm sense). 290d64eccf4SChuanqi Xu // TODO: https://github.com/WebAssembly/tool-conventions/issues/138 291d64eccf4SChuanqi Xu llvm::NamedMDNode *MD = 292d64eccf4SChuanqi Xu M->getOrInsertNamedMetadata("wasm.custom_sections"); 293d64eccf4SChuanqi Xu llvm::Metadata *Ops[2] = { 294d64eccf4SChuanqi Xu llvm::MDString::get(*VMContext, "__clangast"), 295d64eccf4SChuanqi Xu llvm::MDString::get(*VMContext, 296d64eccf4SChuanqi Xu StringRef(SerializedAST.data(), Size))}; 297d64eccf4SChuanqi Xu auto *NameAndContent = llvm::MDTuple::get(*VMContext, Ops); 298d64eccf4SChuanqi Xu MD->addOperand(NameAndContent); 299d64eccf4SChuanqi Xu } else { 300d64eccf4SChuanqi Xu auto Int8Ty = llvm::Type::getInt8Ty(*VMContext); 301d64eccf4SChuanqi Xu auto *Ty = llvm::ArrayType::get(Int8Ty, Size); 302d64eccf4SChuanqi Xu auto *Data = llvm::ConstantDataArray::getString( 303d64eccf4SChuanqi Xu *VMContext, StringRef(SerializedAST.data(), Size), 304d64eccf4SChuanqi Xu /*AddNull=*/false); 305d64eccf4SChuanqi Xu auto *ASTSym = new llvm::GlobalVariable( 306d64eccf4SChuanqi Xu *M, Ty, /*constant*/ true, llvm::GlobalVariable::InternalLinkage, 307d64eccf4SChuanqi Xu Data, "__clang_ast"); 308d64eccf4SChuanqi Xu // The on-disk hashtable needs to be aligned. 309d64eccf4SChuanqi Xu ASTSym->setAlignment(llvm::Align(8)); 310d64eccf4SChuanqi Xu 311d64eccf4SChuanqi Xu // Mach-O also needs a segment name. 312d64eccf4SChuanqi Xu if (Triple.isOSBinFormatMachO()) 313d64eccf4SChuanqi Xu ASTSym->setSection("__CLANG,__clangast"); 314d64eccf4SChuanqi Xu // COFF has an eight character length limit. 315d64eccf4SChuanqi Xu else if (Triple.isOSBinFormatCOFF()) 316d64eccf4SChuanqi Xu ASTSym->setSection("clangast"); 317d64eccf4SChuanqi Xu else 318d64eccf4SChuanqi Xu ASTSym->setSection("__clangast"); 319d64eccf4SChuanqi Xu } 320d64eccf4SChuanqi Xu 321d64eccf4SChuanqi Xu LLVM_DEBUG({ 322d64eccf4SChuanqi Xu // Print the IR for the PCH container to the debug output. 323d64eccf4SChuanqi Xu llvm::SmallString<0> Buffer; 32448d0eb51SFangrui Song clang::emitBackendOutput( 325*9fbf5cfeSBen Langmuir CI, CodeGenOpts, Ctx.getTargetInfo().getDataLayoutString(), M.get(), 326d64eccf4SChuanqi Xu BackendAction::Backend_EmitLL, FS, 327d64eccf4SChuanqi Xu std::make_unique<llvm::raw_svector_ostream>(Buffer)); 328d64eccf4SChuanqi Xu llvm::dbgs() << Buffer; 329d64eccf4SChuanqi Xu }); 330d64eccf4SChuanqi Xu 331d64eccf4SChuanqi Xu // Use the LLVM backend to emit the pch container. 332*9fbf5cfeSBen Langmuir clang::emitBackendOutput(CI, CodeGenOpts, 333*9fbf5cfeSBen Langmuir Ctx.getTargetInfo().getDataLayoutString(), M.get(), 334*9fbf5cfeSBen Langmuir BackendAction::Backend_EmitObj, FS, std::move(OS)); 335d64eccf4SChuanqi Xu 336d64eccf4SChuanqi Xu // Free the memory for the temporary buffer. 337d64eccf4SChuanqi Xu llvm::SmallVector<char, 0> Empty; 338d64eccf4SChuanqi Xu SerializedAST = std::move(Empty); 339d64eccf4SChuanqi Xu } 340d64eccf4SChuanqi Xu }; 341d64eccf4SChuanqi Xu 342d64eccf4SChuanqi Xu } // anonymous namespace 343d64eccf4SChuanqi Xu 344d64eccf4SChuanqi Xu std::unique_ptr<ASTConsumer> 345d64eccf4SChuanqi Xu ObjectFilePCHContainerWriter::CreatePCHContainerGenerator( 346d64eccf4SChuanqi Xu CompilerInstance &CI, const std::string &MainFileName, 347d64eccf4SChuanqi Xu const std::string &OutputFileName, 348d64eccf4SChuanqi Xu std::unique_ptr<llvm::raw_pwrite_stream> OS, 349d64eccf4SChuanqi Xu std::shared_ptr<PCHBuffer> Buffer) const { 350d64eccf4SChuanqi Xu return std::make_unique<PCHContainerGenerator>( 351d64eccf4SChuanqi Xu CI, MainFileName, OutputFileName, std::move(OS), Buffer); 352d64eccf4SChuanqi Xu } 353