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