1 //===--- ObjectFilePCHContainerOperations.cpp -----------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "clang/CodeGen/ObjectFilePCHContainerOperations.h" 11 #include "CGDebugInfo.h" 12 #include "CodeGenModule.h" 13 #include "clang/AST/ASTContext.h" 14 #include "clang/AST/DeclObjC.h" 15 #include "clang/AST/Expr.h" 16 #include "clang/AST/RecursiveASTVisitor.h" 17 #include "clang/Basic/Diagnostic.h" 18 #include "clang/Basic/TargetInfo.h" 19 #include "clang/CodeGen/BackendUtil.h" 20 #include "clang/Frontend/CodeGenOptions.h" 21 #include "clang/Serialization/ASTWriter.h" 22 #include "llvm/ADT/StringRef.h" 23 #include "llvm/Bitcode/BitstreamReader.h" 24 #include "llvm/DebugInfo/DWARF/DWARFContext.h" 25 #include "llvm/IR/Constants.h" 26 #include "llvm/IR/DataLayout.h" 27 #include "llvm/IR/LLVMContext.h" 28 #include "llvm/IR/Module.h" 29 #include "llvm/Object/COFF.h" 30 #include "llvm/Object/ObjectFile.h" 31 #include "llvm/Support/TargetRegistry.h" 32 #include "llvm/Support/TargetSelect.h" 33 #include <memory> 34 using namespace clang; 35 36 #define DEBUG_TYPE "pchcontainer" 37 38 namespace { 39 class ModuleContainerGenerator : public ASTConsumer { 40 DiagnosticsEngine &Diags; 41 const std::string MainFileName; 42 ASTContext *Ctx; 43 const HeaderSearchOptions &HeaderSearchOpts; 44 const PreprocessorOptions &PreprocessorOpts; 45 CodeGenOptions CodeGenOpts; 46 const TargetOptions TargetOpts; 47 const LangOptions LangOpts; 48 std::unique_ptr<llvm::LLVMContext> VMContext; 49 std::unique_ptr<llvm::Module> M; 50 std::unique_ptr<CodeGen::CodeGenModule> Builder; 51 raw_pwrite_stream *OS; 52 std::shared_ptr<PCHBuffer> Buffer; 53 54 public: 55 ModuleContainerGenerator( 56 DiagnosticsEngine &diags, 57 const HeaderSearchOptions &HSO, const PreprocessorOptions &PPO, 58 const TargetOptions &TO, const LangOptions &LO, 59 const std::string &MainFileName, const std::string &OutputFileName, 60 raw_pwrite_stream *OS, std::shared_ptr<PCHBuffer> Buffer) 61 : Diags(diags), HeaderSearchOpts(HSO), PreprocessorOpts(PPO), 62 TargetOpts(TO), LangOpts(LO), OS(OS), 63 Buffer(Buffer) { 64 // The debug info output isn't affected by CodeModel and 65 // ThreadModel, but the backend expects them to be nonempty. 66 CodeGenOpts.CodeModel = "default"; 67 CodeGenOpts.ThreadModel = "single"; 68 CodeGenOpts.setDebugInfo(CodeGenOptions::FullDebugInfo); 69 CodeGenOpts.SplitDwarfFile = OutputFileName; 70 } 71 72 virtual ~ModuleContainerGenerator() {} 73 74 void Initialize(ASTContext &Context) override { 75 Ctx = &Context; 76 VMContext.reset(new llvm::LLVMContext()); 77 M.reset(new llvm::Module(MainFileName, *VMContext)); 78 M->setDataLayout(Ctx->getTargetInfo().getTargetDescription()); 79 Builder.reset(new CodeGen::CodeGenModule(*Ctx, HeaderSearchOpts, 80 PreprocessorOpts, CodeGenOpts, 81 *M, M->getDataLayout(), Diags)); 82 } 83 84 /// Emit a container holding the serialized AST. 85 void HandleTranslationUnit(ASTContext &Ctx) override { 86 assert(M && VMContext && Builder); 87 // Delete these on function exit. 88 std::unique_ptr<llvm::LLVMContext> VMContext = std::move(this->VMContext); 89 std::unique_ptr<llvm::Module> M = std::move(this->M); 90 std::unique_ptr<CodeGen::CodeGenModule> Builder = std::move(this->Builder); 91 92 if (Diags.hasErrorOccurred()) 93 return; 94 95 M->setTargetTriple(Ctx.getTargetInfo().getTriple().getTriple()); 96 M->setDataLayout(Ctx.getTargetInfo().getTargetDescription()); 97 98 // Finalize the Builder. 99 if (Builder) 100 Builder->Release(); 101 102 // Initialize the backend if we haven't done so already. 103 llvm::InitializeAllTargetInfos(); 104 llvm::InitializeAllTargets(); 105 llvm::InitializeAllAsmPrinters(); 106 llvm::InitializeAllTargetMCs(); 107 108 // Ensure the target exists. 109 std::string Error; 110 auto Triple = Ctx.getTargetInfo().getTriple(); 111 if (!llvm::TargetRegistry::lookupTarget(Triple.getTriple(), Error)) 112 llvm::report_fatal_error(Error); 113 114 // Emit the serialized Clang AST into its own section. 115 assert(Buffer->IsComplete && "serialization did not complete"); 116 auto &SerializedAST = Buffer->Data; 117 auto Size = SerializedAST.size(); 118 auto Int8Ty = llvm::Type::getInt8Ty(*VMContext); 119 auto *Ty = llvm::ArrayType::get(Int8Ty, Size); 120 auto *Data = llvm::ConstantDataArray:: 121 getString(*VMContext, StringRef(SerializedAST.data(), Size), 122 /*AddNull=*/false); 123 auto *ASTSym = new llvm::GlobalVariable( 124 *M, Ty, /*constant*/ true, llvm::GlobalVariable::InternalLinkage, Data, 125 "__clang_ast"); 126 // The on-disk hashtable needs to be aligned. 127 ASTSym->setAlignment(8); 128 129 // Mach-O also needs a segment name. 130 if (Triple.isOSBinFormatMachO()) 131 ASTSym->setSection("__CLANG,__clangast"); 132 // COFF has an eight character length limit. 133 else if (Triple.isOSBinFormatCOFF()) 134 ASTSym->setSection("clangast"); 135 else 136 ASTSym->setSection("__clangast"); 137 138 DEBUG({ 139 // Print the IR for the PCH container to the debug output. 140 llvm::SmallString<0> Buffer; 141 llvm::raw_svector_ostream OS(Buffer); 142 clang::EmitBackendOutput(Diags, CodeGenOpts, TargetOpts, LangOpts, 143 Ctx.getTargetInfo().getTargetDescription(), 144 M.get(), BackendAction::Backend_EmitLL, &OS); 145 OS.flush(); 146 llvm::dbgs()<<Buffer; 147 }); 148 149 // Use the LLVM backend to emit the pch container. 150 clang::EmitBackendOutput(Diags, CodeGenOpts, TargetOpts, LangOpts, 151 Ctx.getTargetInfo().getTargetDescription(), 152 M.get(), BackendAction::Backend_EmitObj, OS); 153 154 // Make sure the pch container hits disk. 155 OS->flush(); 156 157 // Free the memory for the temporary buffer. 158 llvm::SmallVector<char, 0> Empty; 159 SerializedAST = std::move(Empty); 160 } 161 }; 162 } 163 164 std::unique_ptr<ASTConsumer> 165 ObjectFilePCHContainerOperations::CreatePCHContainerGenerator( 166 DiagnosticsEngine &Diags, const HeaderSearchOptions &HSO, 167 const PreprocessorOptions &PPO, const TargetOptions &TO, 168 const LangOptions &LO, const std::string &MainFileName, 169 const std::string &OutputFileName, llvm::raw_pwrite_stream *OS, 170 std::shared_ptr<PCHBuffer> Buffer) const { 171 return llvm::make_unique<ModuleContainerGenerator> 172 (Diags, HSO, PPO, TO, LO, MainFileName, OutputFileName, OS, Buffer); 173 } 174 175 void ObjectFilePCHContainerOperations::ExtractPCH( 176 llvm::MemoryBufferRef Buffer, llvm::BitstreamReader &StreamFile) const { 177 if (auto OF = llvm::object::ObjectFile::createObjectFile(Buffer)) { 178 auto *Obj = OF.get().get(); 179 bool IsCOFF = isa<llvm::object::COFFObjectFile>(Obj); 180 // Find the clang AST section in the container. 181 for (auto &Section : OF->get()->sections()) { 182 StringRef Name; 183 Section.getName(Name); 184 if ((!IsCOFF && Name == "__clangast") || 185 ( IsCOFF && Name == "clangast")) { 186 StringRef Buf; 187 Section.getContents(Buf); 188 StreamFile.init((const unsigned char *)Buf.begin(), 189 (const unsigned char *)Buf.end()); 190 return; 191 } 192 } 193 } 194 195 // As a fallback, treat the buffer as a raw AST. 196 StreamFile.init((const unsigned char *)Buffer.getBufferStart(), 197 (const unsigned char *)Buffer.getBufferEnd()); 198 return; 199 } 200