1875ed548SDimitry Andric //===--- ObjectFilePCHContainerOperations.cpp -----------------------------===// 2875ed548SDimitry Andric // 3875ed548SDimitry Andric // The LLVM Compiler Infrastructure 4875ed548SDimitry Andric // 5875ed548SDimitry Andric // This file is distributed under the University of Illinois Open Source 6875ed548SDimitry Andric // License. See LICENSE.TXT for details. 7875ed548SDimitry Andric // 8875ed548SDimitry Andric //===----------------------------------------------------------------------===// 9875ed548SDimitry Andric 10875ed548SDimitry Andric #include "clang/CodeGen/ObjectFilePCHContainerOperations.h" 11875ed548SDimitry Andric #include "CGDebugInfo.h" 12875ed548SDimitry Andric #include "CodeGenModule.h" 13875ed548SDimitry Andric #include "clang/AST/ASTContext.h" 14875ed548SDimitry Andric #include "clang/AST/DeclObjC.h" 15875ed548SDimitry Andric #include "clang/AST/Expr.h" 16875ed548SDimitry Andric #include "clang/AST/RecursiveASTVisitor.h" 17875ed548SDimitry Andric #include "clang/Basic/Diagnostic.h" 18875ed548SDimitry Andric #include "clang/Basic/TargetInfo.h" 19875ed548SDimitry Andric #include "clang/CodeGen/BackendUtil.h" 20875ed548SDimitry Andric #include "clang/Frontend/CodeGenOptions.h" 210623d748SDimitry Andric #include "clang/Frontend/CompilerInstance.h" 220623d748SDimitry Andric #include "clang/Lex/HeaderSearch.h" 23e7145dcbSDimitry Andric #include "clang/Lex/Preprocessor.h" 24875ed548SDimitry Andric #include "clang/Serialization/ASTWriter.h" 25875ed548SDimitry Andric #include "llvm/ADT/StringRef.h" 26875ed548SDimitry Andric #include "llvm/Bitcode/BitstreamReader.h" 27875ed548SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFContext.h" 28875ed548SDimitry Andric #include "llvm/IR/Constants.h" 29875ed548SDimitry Andric #include "llvm/IR/DataLayout.h" 30875ed548SDimitry Andric #include "llvm/IR/LLVMContext.h" 31875ed548SDimitry Andric #include "llvm/IR/Module.h" 32875ed548SDimitry Andric #include "llvm/Object/COFF.h" 33875ed548SDimitry Andric #include "llvm/Object/ObjectFile.h" 34e7145dcbSDimitry Andric #include "llvm/Support/Path.h" 35875ed548SDimitry Andric #include "llvm/Support/TargetRegistry.h" 36875ed548SDimitry Andric #include <memory> 37e7145dcbSDimitry Andric #include <utility> 380623d748SDimitry Andric 39875ed548SDimitry Andric using namespace clang; 40875ed548SDimitry Andric 41875ed548SDimitry Andric #define DEBUG_TYPE "pchcontainer" 42875ed548SDimitry Andric 43875ed548SDimitry Andric namespace { 44875ed548SDimitry Andric class PCHContainerGenerator : public ASTConsumer { 45875ed548SDimitry Andric DiagnosticsEngine &Diags; 46875ed548SDimitry Andric const std::string MainFileName; 47e7145dcbSDimitry Andric const std::string OutputFileName; 48875ed548SDimitry Andric ASTContext *Ctx; 490623d748SDimitry Andric ModuleMap &MMap; 50875ed548SDimitry Andric const HeaderSearchOptions &HeaderSearchOpts; 51875ed548SDimitry Andric const PreprocessorOptions &PreprocessorOpts; 52875ed548SDimitry Andric CodeGenOptions CodeGenOpts; 53875ed548SDimitry Andric const TargetOptions TargetOpts; 54875ed548SDimitry Andric const LangOptions LangOpts; 55875ed548SDimitry Andric std::unique_ptr<llvm::LLVMContext> VMContext; 56875ed548SDimitry Andric std::unique_ptr<llvm::Module> M; 57875ed548SDimitry Andric std::unique_ptr<CodeGen::CodeGenModule> Builder; 58e7145dcbSDimitry Andric std::unique_ptr<raw_pwrite_stream> OS; 59875ed548SDimitry Andric std::shared_ptr<PCHBuffer> Buffer; 60875ed548SDimitry Andric 610623d748SDimitry Andric /// Visit every type and emit debug info for it. 620623d748SDimitry Andric struct DebugTypeVisitor : public RecursiveASTVisitor<DebugTypeVisitor> { 630623d748SDimitry Andric clang::CodeGen::CGDebugInfo &DI; 640623d748SDimitry Andric ASTContext &Ctx; 65e7145dcbSDimitry Andric DebugTypeVisitor(clang::CodeGen::CGDebugInfo &DI, ASTContext &Ctx) 66e7145dcbSDimitry Andric : DI(DI), Ctx(Ctx) {} 670623d748SDimitry Andric 680623d748SDimitry Andric /// Determine whether this type can be represented in DWARF. 690623d748SDimitry Andric static bool CanRepresent(const Type *Ty) { 700623d748SDimitry Andric return !Ty->isDependentType() && !Ty->isUndeducedType(); 710623d748SDimitry Andric } 720623d748SDimitry Andric 730623d748SDimitry Andric bool VisitImportDecl(ImportDecl *D) { 740623d748SDimitry Andric auto *Import = cast<ImportDecl>(D); 750623d748SDimitry Andric if (!Import->getImportedOwningModule()) 760623d748SDimitry Andric DI.EmitImportDecl(*Import); 770623d748SDimitry Andric return true; 780623d748SDimitry Andric } 790623d748SDimitry Andric 800623d748SDimitry Andric bool VisitTypeDecl(TypeDecl *D) { 81444ed5c5SDimitry Andric // TagDecls may be deferred until after all decls have been merged and we 82444ed5c5SDimitry Andric // know the complete type. Pure forward declarations will be skipped, but 83444ed5c5SDimitry Andric // they don't need to be emitted into the module anyway. 84e7145dcbSDimitry Andric if (auto *TD = dyn_cast<TagDecl>(D)) 85e7145dcbSDimitry Andric if (!TD->isCompleteDefinition()) 86444ed5c5SDimitry Andric return true; 87444ed5c5SDimitry Andric 880623d748SDimitry Andric QualType QualTy = Ctx.getTypeDeclType(D); 890623d748SDimitry Andric if (!QualTy.isNull() && CanRepresent(QualTy.getTypePtr())) 900623d748SDimitry Andric DI.getOrCreateStandaloneType(QualTy, D->getLocation()); 910623d748SDimitry Andric return true; 920623d748SDimitry Andric } 930623d748SDimitry Andric 940623d748SDimitry Andric bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { 950623d748SDimitry Andric QualType QualTy(D->getTypeForDecl(), 0); 960623d748SDimitry Andric if (!QualTy.isNull() && CanRepresent(QualTy.getTypePtr())) 970623d748SDimitry Andric DI.getOrCreateStandaloneType(QualTy, D->getLocation()); 980623d748SDimitry Andric return true; 990623d748SDimitry Andric } 1000623d748SDimitry Andric 1010623d748SDimitry Andric bool VisitFunctionDecl(FunctionDecl *D) { 1020623d748SDimitry Andric if (isa<CXXMethodDecl>(D)) 1030623d748SDimitry Andric // This is not yet supported. Constructing the `this' argument 1040623d748SDimitry Andric // mandates a CodeGenFunction. 1050623d748SDimitry Andric return true; 1060623d748SDimitry Andric 1070623d748SDimitry Andric SmallVector<QualType, 16> ArgTypes; 108e7145dcbSDimitry Andric for (auto i : D->parameters()) 1090623d748SDimitry Andric ArgTypes.push_back(i->getType()); 1100623d748SDimitry Andric QualType RetTy = D->getReturnType(); 1110623d748SDimitry Andric QualType FnTy = Ctx.getFunctionType(RetTy, ArgTypes, 1120623d748SDimitry Andric FunctionProtoType::ExtProtoInfo()); 1130623d748SDimitry Andric if (CanRepresent(FnTy.getTypePtr())) 1140623d748SDimitry Andric DI.EmitFunctionDecl(D, D->getLocation(), FnTy); 1150623d748SDimitry Andric return true; 1160623d748SDimitry Andric } 1170623d748SDimitry Andric 1180623d748SDimitry Andric bool VisitObjCMethodDecl(ObjCMethodDecl *D) { 1190623d748SDimitry Andric if (!D->getClassInterface()) 1200623d748SDimitry Andric return true; 1210623d748SDimitry Andric 1220623d748SDimitry Andric bool selfIsPseudoStrong, selfIsConsumed; 1230623d748SDimitry Andric SmallVector<QualType, 16> ArgTypes; 1240623d748SDimitry Andric ArgTypes.push_back(D->getSelfType(Ctx, D->getClassInterface(), 1250623d748SDimitry Andric selfIsPseudoStrong, selfIsConsumed)); 1260623d748SDimitry Andric ArgTypes.push_back(Ctx.getObjCSelType()); 127e7145dcbSDimitry Andric for (auto i : D->parameters()) 1280623d748SDimitry Andric ArgTypes.push_back(i->getType()); 1290623d748SDimitry Andric QualType RetTy = D->getReturnType(); 1300623d748SDimitry Andric QualType FnTy = Ctx.getFunctionType(RetTy, ArgTypes, 1310623d748SDimitry Andric FunctionProtoType::ExtProtoInfo()); 1320623d748SDimitry Andric if (CanRepresent(FnTy.getTypePtr())) 1330623d748SDimitry Andric DI.EmitFunctionDecl(D, D->getLocation(), FnTy); 1340623d748SDimitry Andric return true; 1350623d748SDimitry Andric } 1360623d748SDimitry Andric }; 1370623d748SDimitry Andric 138875ed548SDimitry Andric public: 1390623d748SDimitry Andric PCHContainerGenerator(CompilerInstance &CI, const std::string &MainFileName, 140875ed548SDimitry Andric const std::string &OutputFileName, 141e7145dcbSDimitry Andric std::unique_ptr<raw_pwrite_stream> OS, 142875ed548SDimitry Andric std::shared_ptr<PCHBuffer> Buffer) 143e7145dcbSDimitry Andric : Diags(CI.getDiagnostics()), MainFileName(MainFileName), 144e7145dcbSDimitry Andric OutputFileName(OutputFileName), Ctx(nullptr), 1450623d748SDimitry Andric MMap(CI.getPreprocessor().getHeaderSearchInfo().getModuleMap()), 1460623d748SDimitry Andric HeaderSearchOpts(CI.getHeaderSearchOpts()), 1470623d748SDimitry Andric PreprocessorOpts(CI.getPreprocessorOpts()), 148e7145dcbSDimitry Andric TargetOpts(CI.getTargetOpts()), LangOpts(CI.getLangOpts()), 149e7145dcbSDimitry Andric OS(std::move(OS)), Buffer(std::move(Buffer)) { 150875ed548SDimitry Andric // The debug info output isn't affected by CodeModel and 151875ed548SDimitry Andric // ThreadModel, but the backend expects them to be nonempty. 152875ed548SDimitry Andric CodeGenOpts.CodeModel = "default"; 153875ed548SDimitry Andric CodeGenOpts.ThreadModel = "single"; 1540623d748SDimitry Andric CodeGenOpts.DebugTypeExtRefs = true; 155e7145dcbSDimitry Andric CodeGenOpts.setDebugInfo(codegenoptions::FullDebugInfo); 156e7145dcbSDimitry Andric CodeGenOpts.setDebuggerTuning(CI.getCodeGenOpts().getDebuggerTuning()); 157875ed548SDimitry Andric } 158875ed548SDimitry Andric 1590623d748SDimitry Andric ~PCHContainerGenerator() override = default; 160875ed548SDimitry Andric 161875ed548SDimitry Andric void Initialize(ASTContext &Context) override { 1620623d748SDimitry Andric assert(!Ctx && "initialized multiple times"); 1630623d748SDimitry Andric 164875ed548SDimitry Andric Ctx = &Context; 165875ed548SDimitry Andric VMContext.reset(new llvm::LLVMContext()); 166875ed548SDimitry Andric M.reset(new llvm::Module(MainFileName, *VMContext)); 167e7145dcbSDimitry Andric M->setDataLayout(Ctx->getTargetInfo().getDataLayout()); 1680623d748SDimitry Andric Builder.reset(new CodeGen::CodeGenModule( 1690623d748SDimitry Andric *Ctx, HeaderSearchOpts, PreprocessorOpts, CodeGenOpts, *M, Diags)); 170e7145dcbSDimitry Andric 171e7145dcbSDimitry Andric // Prepare CGDebugInfo to emit debug info for a clang module. 172e7145dcbSDimitry Andric auto *DI = Builder->getModuleDebugInfo(); 173e7145dcbSDimitry Andric StringRef ModuleName = llvm::sys::path::filename(MainFileName); 174e7145dcbSDimitry Andric DI->setPCHDescriptor({ModuleName, "", OutputFileName, ~1ULL}); 175e7145dcbSDimitry Andric DI->setModuleMap(MMap); 1760623d748SDimitry Andric } 1770623d748SDimitry Andric 1780623d748SDimitry Andric bool HandleTopLevelDecl(DeclGroupRef D) override { 1790623d748SDimitry Andric if (Diags.hasErrorOccurred()) 1800623d748SDimitry Andric return true; 1810623d748SDimitry Andric 1820623d748SDimitry Andric // Collect debug info for all decls in this group. 1830623d748SDimitry Andric for (auto *I : D) 1840623d748SDimitry Andric if (!I->isFromASTFile()) { 185e7145dcbSDimitry Andric DebugTypeVisitor DTV(*Builder->getModuleDebugInfo(), *Ctx); 1860623d748SDimitry Andric DTV.TraverseDecl(I); 1870623d748SDimitry Andric } 1880623d748SDimitry Andric return true; 1890623d748SDimitry Andric } 1900623d748SDimitry Andric 1910623d748SDimitry Andric void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override { 1920623d748SDimitry Andric HandleTopLevelDecl(D); 1930623d748SDimitry Andric } 1940623d748SDimitry Andric 1950623d748SDimitry Andric void HandleTagDeclDefinition(TagDecl *D) override { 1960623d748SDimitry Andric if (Diags.hasErrorOccurred()) 1970623d748SDimitry Andric return; 1980623d748SDimitry Andric 199444ed5c5SDimitry Andric if (D->isFromASTFile()) 200444ed5c5SDimitry Andric return; 201444ed5c5SDimitry Andric 202e7145dcbSDimitry Andric // Anonymous tag decls are deferred until we are building their declcontext. 203e7145dcbSDimitry Andric if (D->getName().empty()) 204e7145dcbSDimitry Andric return; 205e7145dcbSDimitry Andric 206e7145dcbSDimitry Andric // Defer tag decls until their declcontext is complete. 207e7145dcbSDimitry Andric auto *DeclCtx = D->getDeclContext(); 208e7145dcbSDimitry Andric while (DeclCtx) { 209e7145dcbSDimitry Andric if (auto *D = dyn_cast<TagDecl>(DeclCtx)) 210e7145dcbSDimitry Andric if (!D->isCompleteDefinition()) 211e7145dcbSDimitry Andric return; 212e7145dcbSDimitry Andric DeclCtx = DeclCtx->getParent(); 213e7145dcbSDimitry Andric } 214e7145dcbSDimitry Andric 215e7145dcbSDimitry Andric DebugTypeVisitor DTV(*Builder->getModuleDebugInfo(), *Ctx); 216444ed5c5SDimitry Andric DTV.TraverseDecl(D); 2170623d748SDimitry Andric Builder->UpdateCompletedType(D); 2180623d748SDimitry Andric } 2190623d748SDimitry Andric 2200623d748SDimitry Andric void HandleTagDeclRequiredDefinition(const TagDecl *D) override { 2210623d748SDimitry Andric if (Diags.hasErrorOccurred()) 2220623d748SDimitry Andric return; 2230623d748SDimitry Andric 2240623d748SDimitry Andric if (const RecordDecl *RD = dyn_cast<RecordDecl>(D)) 2250623d748SDimitry Andric Builder->getModuleDebugInfo()->completeRequiredType(RD); 226875ed548SDimitry Andric } 227875ed548SDimitry Andric 228875ed548SDimitry Andric /// Emit a container holding the serialized AST. 229875ed548SDimitry Andric void HandleTranslationUnit(ASTContext &Ctx) override { 230875ed548SDimitry Andric assert(M && VMContext && Builder); 231875ed548SDimitry Andric // Delete these on function exit. 232875ed548SDimitry Andric std::unique_ptr<llvm::LLVMContext> VMContext = std::move(this->VMContext); 233875ed548SDimitry Andric std::unique_ptr<llvm::Module> M = std::move(this->M); 234875ed548SDimitry Andric std::unique_ptr<CodeGen::CodeGenModule> Builder = std::move(this->Builder); 235875ed548SDimitry Andric 236875ed548SDimitry Andric if (Diags.hasErrorOccurred()) 237875ed548SDimitry Andric return; 238875ed548SDimitry Andric 239875ed548SDimitry Andric M->setTargetTriple(Ctx.getTargetInfo().getTriple().getTriple()); 240e7145dcbSDimitry Andric M->setDataLayout(Ctx.getTargetInfo().getDataLayout()); 241e7145dcbSDimitry Andric 242e7145dcbSDimitry Andric // PCH files don't have a signature field in the control block, 243e7145dcbSDimitry Andric // but LLVM detects DWO CUs by looking for a non-zero DWO id. 244e7145dcbSDimitry Andric uint64_t Signature = Buffer->Signature ? Buffer->Signature : ~1ULL; 245e7145dcbSDimitry Andric Builder->getModuleDebugInfo()->setDwoId(Signature); 246875ed548SDimitry Andric 247875ed548SDimitry Andric // Finalize the Builder. 248875ed548SDimitry Andric if (Builder) 249875ed548SDimitry Andric Builder->Release(); 250875ed548SDimitry Andric 251875ed548SDimitry Andric // Ensure the target exists. 252875ed548SDimitry Andric std::string Error; 253875ed548SDimitry Andric auto Triple = Ctx.getTargetInfo().getTriple(); 254875ed548SDimitry Andric if (!llvm::TargetRegistry::lookupTarget(Triple.getTriple(), Error)) 255875ed548SDimitry Andric llvm::report_fatal_error(Error); 256875ed548SDimitry Andric 257875ed548SDimitry Andric // Emit the serialized Clang AST into its own section. 258875ed548SDimitry Andric assert(Buffer->IsComplete && "serialization did not complete"); 259875ed548SDimitry Andric auto &SerializedAST = Buffer->Data; 260875ed548SDimitry Andric auto Size = SerializedAST.size(); 261875ed548SDimitry Andric auto Int8Ty = llvm::Type::getInt8Ty(*VMContext); 262875ed548SDimitry Andric auto *Ty = llvm::ArrayType::get(Int8Ty, Size); 263875ed548SDimitry Andric auto *Data = llvm::ConstantDataArray::getString( 264875ed548SDimitry Andric *VMContext, StringRef(SerializedAST.data(), Size), 265875ed548SDimitry Andric /*AddNull=*/false); 266875ed548SDimitry Andric auto *ASTSym = new llvm::GlobalVariable( 267875ed548SDimitry Andric *M, Ty, /*constant*/ true, llvm::GlobalVariable::InternalLinkage, Data, 268875ed548SDimitry Andric "__clang_ast"); 269875ed548SDimitry Andric // The on-disk hashtable needs to be aligned. 270875ed548SDimitry Andric ASTSym->setAlignment(8); 271875ed548SDimitry Andric 272875ed548SDimitry Andric // Mach-O also needs a segment name. 273875ed548SDimitry Andric if (Triple.isOSBinFormatMachO()) 274875ed548SDimitry Andric ASTSym->setSection("__CLANG,__clangast"); 275875ed548SDimitry Andric // COFF has an eight character length limit. 276875ed548SDimitry Andric else if (Triple.isOSBinFormatCOFF()) 277875ed548SDimitry Andric ASTSym->setSection("clangast"); 278875ed548SDimitry Andric else 279875ed548SDimitry Andric ASTSym->setSection("__clangast"); 280875ed548SDimitry Andric 281875ed548SDimitry Andric DEBUG({ 282875ed548SDimitry Andric // Print the IR for the PCH container to the debug output. 283875ed548SDimitry Andric llvm::SmallString<0> Buffer; 284e7145dcbSDimitry Andric clang::EmitBackendOutput( 285e7145dcbSDimitry Andric Diags, CodeGenOpts, TargetOpts, LangOpts, 286e7145dcbSDimitry Andric Ctx.getTargetInfo().getDataLayout(), M.get(), 287e7145dcbSDimitry Andric BackendAction::Backend_EmitLL, 288e7145dcbSDimitry Andric llvm::make_unique<llvm::raw_svector_ostream>(Buffer)); 289875ed548SDimitry Andric llvm::dbgs() << Buffer; 290875ed548SDimitry Andric }); 291875ed548SDimitry Andric 292875ed548SDimitry Andric // Use the LLVM backend to emit the pch container. 293875ed548SDimitry Andric clang::EmitBackendOutput(Diags, CodeGenOpts, TargetOpts, LangOpts, 294e7145dcbSDimitry Andric Ctx.getTargetInfo().getDataLayout(), M.get(), 295e7145dcbSDimitry Andric BackendAction::Backend_EmitObj, std::move(OS)); 296875ed548SDimitry Andric 297875ed548SDimitry Andric // Free the memory for the temporary buffer. 298875ed548SDimitry Andric llvm::SmallVector<char, 0> Empty; 299875ed548SDimitry Andric SerializedAST = std::move(Empty); 300875ed548SDimitry Andric } 301875ed548SDimitry Andric }; 302875ed548SDimitry Andric 3030623d748SDimitry Andric } // anonymous namespace 304875ed548SDimitry Andric 305875ed548SDimitry Andric std::unique_ptr<ASTConsumer> 306b6c25e0eSDimitry Andric ObjectFilePCHContainerWriter::CreatePCHContainerGenerator( 3070623d748SDimitry Andric CompilerInstance &CI, const std::string &MainFileName, 308e7145dcbSDimitry Andric const std::string &OutputFileName, 309e7145dcbSDimitry Andric std::unique_ptr<llvm::raw_pwrite_stream> OS, 310875ed548SDimitry Andric std::shared_ptr<PCHBuffer> Buffer) const { 311e7145dcbSDimitry Andric return llvm::make_unique<PCHContainerGenerator>( 312e7145dcbSDimitry Andric CI, MainFileName, OutputFileName, std::move(OS), Buffer); 313875ed548SDimitry Andric } 314875ed548SDimitry Andric 315b6c25e0eSDimitry Andric void ObjectFilePCHContainerReader::ExtractPCH( 316875ed548SDimitry Andric llvm::MemoryBufferRef Buffer, llvm::BitstreamReader &StreamFile) const { 317875ed548SDimitry Andric if (auto OF = llvm::object::ObjectFile::createObjectFile(Buffer)) { 318875ed548SDimitry Andric auto *Obj = OF.get().get(); 319875ed548SDimitry Andric bool IsCOFF = isa<llvm::object::COFFObjectFile>(Obj); 320875ed548SDimitry Andric // Find the clang AST section in the container. 321875ed548SDimitry Andric for (auto &Section : OF->get()->sections()) { 322875ed548SDimitry Andric StringRef Name; 323875ed548SDimitry Andric Section.getName(Name); 324875ed548SDimitry Andric if ((!IsCOFF && Name == "__clangast") || 325875ed548SDimitry Andric ( IsCOFF && Name == "clangast")) { 326875ed548SDimitry Andric StringRef Buf; 327875ed548SDimitry Andric Section.getContents(Buf); 328875ed548SDimitry Andric StreamFile.init((const unsigned char *)Buf.begin(), 329875ed548SDimitry Andric (const unsigned char *)Buf.end()); 330875ed548SDimitry Andric return; 331875ed548SDimitry Andric } 332875ed548SDimitry Andric } 333875ed548SDimitry Andric } 334875ed548SDimitry Andric 335875ed548SDimitry Andric // As a fallback, treat the buffer as a raw AST. 336875ed548SDimitry Andric StreamFile.init((const unsigned char *)Buffer.getBufferStart(), 337875ed548SDimitry Andric (const unsigned char *)Buffer.getBufferEnd()); 338875ed548SDimitry Andric } 339