clang 22.0.0git
ModuleBuilder.cpp
Go to the documentation of this file.
1//===--- ModuleBuilder.cpp - Emit LLVM Code from ASTs ---------------------===//
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// This builds an AST and converts it to LLVM Code.
10//
11//===----------------------------------------------------------------------===//
12
14#include "CGDebugInfo.h"
15#include "CodeGenModule.h"
17#include "clang/AST/DeclObjC.h"
18#include "clang/AST/Expr.h"
22#include "llvm/ADT/StringRef.h"
23#include "llvm/IR/DataLayout.h"
24#include "llvm/IR/LLVMContext.h"
25#include "llvm/IR/Module.h"
26#include "llvm/Support/FormatVariadic.h"
27#include "llvm/Support/VirtualFileSystem.h"
28#include <memory>
29
30using namespace clang;
31using namespace CodeGen;
32
33namespace {
34 class CodeGeneratorImpl : public CodeGenerator {
35 DiagnosticsEngine &Diags;
36 ASTContext *Ctx;
37 IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS; // Only used for debug info.
38 const HeaderSearchOptions &HeaderSearchOpts; // Only used for debug info.
39 const PreprocessorOptions &PreprocessorOpts; // Only used for debug info.
40 const CodeGenOptions &CodeGenOpts;
41
42 unsigned HandlingTopLevelDecls;
43
44 /// Use this when emitting decls to block re-entrant decl emission. It will
45 /// emit all deferred decls on scope exit. Set EmitDeferred to false if decl
46 /// emission must be deferred longer, like at the end of a tag definition.
47 struct HandlingTopLevelDeclRAII {
48 CodeGeneratorImpl &Self;
49 bool EmitDeferred;
50 HandlingTopLevelDeclRAII(CodeGeneratorImpl &Self,
51 bool EmitDeferred = true)
52 : Self(Self), EmitDeferred(EmitDeferred) {
53 ++Self.HandlingTopLevelDecls;
54 }
55 ~HandlingTopLevelDeclRAII() {
56 unsigned Level = --Self.HandlingTopLevelDecls;
57 if (Level == 0 && EmitDeferred)
58 Self.EmitDeferredDecls();
59 }
60 };
61
62 CoverageSourceInfo *CoverageInfo;
63
64 protected:
65 std::unique_ptr<llvm::Module> M;
66 std::unique_ptr<CodeGen::CodeGenModule> Builder;
67
68 private:
69 SmallVector<FunctionDecl *, 8> DeferredInlineMemberFuncDefs;
70
71 static llvm::StringRef ExpandModuleName(llvm::StringRef ModuleName,
72 const CodeGenOptions &CGO) {
73 if (ModuleName == "-" && !CGO.MainFileName.empty())
74 return CGO.MainFileName;
75 return ModuleName;
76 }
77
78 public:
79 CodeGeneratorImpl(DiagnosticsEngine &diags, llvm::StringRef ModuleName,
80 IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
81 const HeaderSearchOptions &HSO,
82 const PreprocessorOptions &PPO, const CodeGenOptions &CGO,
83 llvm::LLVMContext &C,
84 CoverageSourceInfo *CoverageInfo = nullptr)
85 : Diags(diags), Ctx(nullptr), FS(std::move(FS)), HeaderSearchOpts(HSO),
86 PreprocessorOpts(PPO), CodeGenOpts(CGO), HandlingTopLevelDecls(0),
87 CoverageInfo(CoverageInfo),
88 M(new llvm::Module(ExpandModuleName(ModuleName, CGO), C)) {
89 C.setDiscardValueNames(CGO.DiscardValueNames);
90 }
91
92 ~CodeGeneratorImpl() override {
93 // There should normally not be any leftover inline method definitions.
94 assert(DeferredInlineMemberFuncDefs.empty() ||
95 Diags.hasErrorOccurred());
96 }
97
98 CodeGenModule &CGM() {
99 return *Builder;
100 }
101
102 llvm::Module *GetModule() {
103 return M.get();
104 }
105
106 CGDebugInfo *getCGDebugInfo() {
107 return Builder->getModuleDebugInfo();
108 }
109
110 llvm::Module *ReleaseModule() {
111 return M.release();
112 }
113
114 const Decl *GetDeclForMangledName(StringRef MangledName) {
115 GlobalDecl Result;
116 if (!Builder->lookupRepresentativeDecl(MangledName, Result))
117 return nullptr;
118 const Decl *D = Result.getCanonicalDecl().getDecl();
119 if (auto FD = dyn_cast<FunctionDecl>(D)) {
120 if (FD->hasBody(FD))
121 return FD;
122 } else if (auto TD = dyn_cast<TagDecl>(D)) {
123 if (auto Def = TD->getDefinition())
124 return Def;
125 }
126 return D;
127 }
128
129 llvm::StringRef GetMangledName(GlobalDecl GD) {
130 return Builder->getMangledName(GD);
131 }
132
133 llvm::Constant *GetAddrOfGlobal(GlobalDecl global, bool isForDefinition) {
134 return Builder->GetAddrOfGlobal(global, ForDefinition_t(isForDefinition));
135 }
136
137 llvm::Module *StartModule(llvm::StringRef ModuleName,
138 llvm::LLVMContext &C) {
139 assert(!M && "Replacing existing Module?");
140 M.reset(new llvm::Module(ExpandModuleName(ModuleName, CodeGenOpts), C));
141
142 IRGenFinished = false;
143
144 std::unique_ptr<CodeGenModule> OldBuilder = std::move(Builder);
145
146 Initialize(*Ctx);
147
148 if (OldBuilder)
149 OldBuilder->moveLazyEmissionStates(Builder.get());
150
151 return M.get();
152 }
153
154 void Initialize(ASTContext &Context) override {
155 Ctx = &Context;
156
157 M->setTargetTriple(Ctx->getTargetInfo().getTriple());
158 M->setDataLayout(Ctx->getTargetInfo().getDataLayoutString());
159 const auto &SDKVersion = Ctx->getTargetInfo().getSDKVersion();
160 if (!SDKVersion.empty())
161 M->setSDKVersion(SDKVersion);
162 if (const auto *TVT = Ctx->getTargetInfo().getDarwinTargetVariantTriple())
163 M->setDarwinTargetVariantTriple(TVT->getTriple());
164 if (auto TVSDKVersion =
165 Ctx->getTargetInfo().getDarwinTargetVariantSDKVersion())
166 M->setDarwinTargetVariantSDKVersion(*TVSDKVersion);
167 Builder.reset(new CodeGen::CodeGenModule(Context, FS, HeaderSearchOpts,
168 PreprocessorOpts, CodeGenOpts,
169 *M, Diags, CoverageInfo));
170
171 for (auto &&Lib : CodeGenOpts.DependentLibraries)
172 Builder->AddDependentLib(Lib);
173 for (auto &&Opt : CodeGenOpts.LinkerOptions)
174 Builder->AppendLinkerOptions(Opt);
175 }
176
177 void HandleCXXStaticMemberVarInstantiation(VarDecl *VD) override {
178 if (Diags.hasErrorOccurred())
179 return;
180
181 Builder->HandleCXXStaticMemberVarInstantiation(VD);
182 }
183
184 bool HandleTopLevelDecl(DeclGroupRef DG) override {
185 // Ignore interesting decls from the AST reader after IRGen is finished.
186 if (IRGenFinished)
187 return true; // We can't CodeGen more but pass to other consumers.
188
189 // FIXME: Why not return false and abort parsing?
190 if (Diags.hasUnrecoverableErrorOccurred())
191 return true;
192
193 HandlingTopLevelDeclRAII HandlingDecl(*this);
194
195 // Make sure to emit all elements of a Decl.
196 for (auto &I : DG)
197 Builder->EmitTopLevelDecl(I);
198
199 return true;
200 }
201
202 void EmitDeferredDecls() {
203 if (DeferredInlineMemberFuncDefs.empty())
204 return;
205
206 // Emit any deferred inline method definitions. Note that more deferred
207 // methods may be added during this loop, since ASTConsumer callbacks
208 // can be invoked if AST inspection results in declarations being added.
209 HandlingTopLevelDeclRAII HandlingDecl(*this);
210 for (unsigned I = 0; I != DeferredInlineMemberFuncDefs.size(); ++I)
211 Builder->EmitTopLevelDecl(DeferredInlineMemberFuncDefs[I]);
212 DeferredInlineMemberFuncDefs.clear();
213 }
214
215 void HandleInlineFunctionDefinition(FunctionDecl *D) override {
216 if (Diags.hasUnrecoverableErrorOccurred())
217 return;
218
219 assert(D->doesThisDeclarationHaveABody());
220
221 // We may want to emit this definition. However, that decision might be
222 // based on computing the linkage, and we have to defer that in case we
223 // are inside of something that will change the method's final linkage,
224 // e.g.
225 // typedef struct {
226 // void bar();
227 // void foo() { bar(); }
228 // } A;
229 DeferredInlineMemberFuncDefs.push_back(D);
230
231 // Provide some coverage mapping even for methods that aren't emitted.
232 // Don't do this for templated classes though, as they may not be
233 // instantiable.
235 Builder->AddDeferredUnusedCoverageMapping(D);
236 }
237
238 /// HandleTagDeclDefinition - This callback is invoked each time a TagDecl
239 /// to (e.g. struct, union, enum, class) is completed. This allows the
240 /// client hack on the type, which can occur at any point in the file
241 /// (because these can be defined in declspecs).
242 void HandleTagDeclDefinition(TagDecl *D) override {
243 if (Diags.hasUnrecoverableErrorOccurred())
244 return;
245
246 // Don't allow re-entrant calls to CodeGen triggered by PCH
247 // deserialization to emit deferred decls.
248 HandlingTopLevelDeclRAII HandlingDecl(*this, /*EmitDeferred=*/false);
249
250 Builder->UpdateCompletedType(D);
251
252 // For MSVC compatibility, treat declarations of static data members with
253 // inline initializers as definitions.
254 if (Ctx->getTargetInfo().getCXXABI().isMicrosoft()) {
255 for (Decl *Member : D->decls()) {
256 if (VarDecl *VD = dyn_cast<VarDecl>(Member)) {
257 if (Ctx->isMSStaticDataMemberInlineDefinition(VD) &&
258 Ctx->DeclMustBeEmitted(VD)) {
259 Builder->EmitGlobal(VD);
260 }
261 }
262 }
263 }
264 // For OpenMP emit declare reduction functions, if required.
265 if (Ctx->getLangOpts().OpenMP) {
266 for (Decl *Member : D->decls()) {
267 if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(Member)) {
268 if (Ctx->DeclMustBeEmitted(DRD))
269 Builder->EmitGlobal(DRD);
270 } else if (auto *DMD = dyn_cast<OMPDeclareMapperDecl>(Member)) {
271 if (Ctx->DeclMustBeEmitted(DMD))
272 Builder->EmitGlobal(DMD);
273 }
274 }
275 }
276 }
277
278 void HandleTagDeclRequiredDefinition(const TagDecl *D) override {
279 if (Diags.hasUnrecoverableErrorOccurred())
280 return;
281
282 // Don't allow re-entrant calls to CodeGen triggered by PCH
283 // deserialization to emit deferred decls.
284 HandlingTopLevelDeclRAII HandlingDecl(*this, /*EmitDeferred=*/false);
285
286 if (CodeGen::CGDebugInfo *DI = Builder->getModuleDebugInfo())
287 if (const RecordDecl *RD = dyn_cast<RecordDecl>(D))
288 DI->completeRequiredType(RD);
289 }
290
291 void HandleTranslationUnit(ASTContext &Ctx) override {
292 // Release the Builder when there is no error.
293 if (!Diags.hasUnrecoverableErrorOccurred() && Builder)
294 Builder->Release();
295
296 // If there are errors before or when releasing the Builder, reset
297 // the module to stop here before invoking the backend.
298 if (Diags.hasErrorOccurred()) {
299 if (Builder)
300 Builder->clear();
301 M.reset();
302 }
303
304 IRGenFinished = true;
305 }
306
307 void AssignInheritanceModel(CXXRecordDecl *RD) override {
308 if (Diags.hasUnrecoverableErrorOccurred())
309 return;
310
311 Builder->RefreshTypeCacheForClass(RD);
312 }
313
314 void CompleteTentativeDefinition(VarDecl *D) override {
315 if (Diags.hasUnrecoverableErrorOccurred())
316 return;
317
318 Builder->EmitTentativeDefinition(D);
319 }
320
321 void CompleteExternalDeclaration(DeclaratorDecl *D) override {
322 Builder->EmitExternalDeclaration(D);
323 }
324
325 void HandleVTable(CXXRecordDecl *RD) override {
326 if (Diags.hasUnrecoverableErrorOccurred())
327 return;
328
329 Builder->EmitVTable(RD);
330 }
331 };
332}
333
334void CodeGenerator::anchor() { }
335
337 return static_cast<CodeGeneratorImpl*>(this)->CGM();
338}
339
341 return static_cast<CodeGeneratorImpl*>(this)->GetModule();
342}
343
345 return static_cast<CodeGeneratorImpl*>(this)->ReleaseModule();
346}
347
349 return static_cast<CodeGeneratorImpl*>(this)->getCGDebugInfo();
350}
351
352const Decl *CodeGenerator::GetDeclForMangledName(llvm::StringRef name) {
353 return static_cast<CodeGeneratorImpl*>(this)->GetDeclForMangledName(name);
354}
355
357 return static_cast<CodeGeneratorImpl *>(this)->GetMangledName(GD);
358}
359
361 bool isForDefinition) {
362 return static_cast<CodeGeneratorImpl*>(this)
363 ->GetAddrOfGlobal(global, isForDefinition);
364}
365
366llvm::Module *CodeGenerator::StartModule(llvm::StringRef ModuleName,
367 llvm::LLVMContext &C) {
368 return static_cast<CodeGeneratorImpl*>(this)->StartModule(ModuleName, C);
369}
370
372clang::CreateLLVMCodeGen(DiagnosticsEngine &Diags, llvm::StringRef ModuleName,
374 const HeaderSearchOptions &HeaderSearchOpts,
375 const PreprocessorOptions &PreprocessorOpts,
376 const CodeGenOptions &CGO, llvm::LLVMContext &C,
377 CoverageSourceInfo *CoverageInfo) {
378 return new CodeGeneratorImpl(Diags, ModuleName, std::move(FS),
379 HeaderSearchOpts, PreprocessorOpts, CGO, C,
380 CoverageInfo);
381}
382
383namespace clang {
384namespace CodeGen {
385std::optional<std::pair<StringRef, StringRef>>
386DemangleTrapReasonInDebugInfo(StringRef FuncName) {
387 static auto TrapRegex =
388 llvm::Regex(llvm::formatv("^{0}\\$(.*)\\$(.*)$", ClangTrapPrefix).str());
390 std::string *ErrorPtr = nullptr;
391#ifndef NDEBUG
392 std::string Error;
393 ErrorPtr = &Error;
394#endif
395 if (!TrapRegex.match(FuncName, &Matches, ErrorPtr)) {
396 assert(ErrorPtr && ErrorPtr->empty() && "Invalid regex pattern");
397 return {};
398 }
399
400 if (Matches.size() != 3) {
401 assert(0 && "Expected 3 matches from Regex::match");
402 return {};
403 }
404
405 // Returns { Trap Category, Trap Message }
406 return std::make_pair(Matches[1], Matches[2]);
407}
408} // namespace CodeGen
409} // namespace clang
Defines the clang::ASTContext interface.
Defines the Diagnostic-related interfaces.
constexpr llvm::StringRef ClangTrapPrefix
const TargetInfo & getTargetInfo() const
Definition ASTContext.h:891
CodeGenOptions - Track various options which control how the code is optimized and passed to the back...
std::string MainFileName
The user provided name for the "main file", if non-empty.
This class gathers all debug information during compilation and is responsible for emitting to llvm g...
Definition CGDebugInfo.h:59
This class organizes the cross-function state that is used while generating LLVM code.
The primary public interface to the Clang code generator.
llvm::Module * ReleaseModule()
Release ownership of the module to the caller.
const Decl * GetDeclForMangledName(llvm::StringRef MangledName)
Given a mangled name, return a declaration which mangles that way which has been added to this code g...
llvm::Module * StartModule(llvm::StringRef ModuleName, llvm::LLVMContext &C)
Create a new llvm::Module after calling HandleTranslationUnit.
llvm::Constant * GetAddrOfGlobal(GlobalDecl decl, bool isForDefinition)
Return the LLVM address of the given global entity.
llvm::StringRef GetMangledName(GlobalDecl GD)
Given a global declaration, return a mangled name for this declaration which has been added to this c...
CodeGen::CGDebugInfo * getCGDebugInfo()
Return debug info code generator.
CodeGen::CodeGenModule & CGM()
Return an opaque reference to the CodeGenModule object, which can be used in various secondary APIs.
llvm::Module * GetModule()
Return the module that this code generator is building into.
Stores additional source code information like skipped ranges which is required by the coverage mappi...
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
Definition DeclBase.h:2373
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
DeclContext * getLexicalDeclContext()
getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC).
Definition DeclBase.h:918
Concrete class used by the front-end to report problems and issues.
Definition Diagnostic.h:232
bool doesThisDeclarationHaveABody() const
Returns whether this specific declaration of the function has a body.
Definition Decl.h:2326
GlobalDecl - represents a global declaration.
Definition GlobalDecl.h:57
HeaderSearchOptions - Helper class for storing options related to the initialization of the HeaderSea...
PreprocessorOptions - This class is used for passing the various options used in preprocessor initial...
const llvm::VersionTuple & getSDKVersion() const
Defines the clang::TargetInfo interface.
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
Definition CGValue.h:145
std::optional< std::pair< StringRef, StringRef > > DemangleTrapReasonInDebugInfo(StringRef FuncName)
Demangle the artificial function name (.
The JSON file list parser is used to communicate input to InstallAPI.
CodeGenerator * CreateLLVMCodeGen(DiagnosticsEngine &Diags, llvm::StringRef ModuleName, IntrusiveRefCntPtr< llvm::vfs::FileSystem > FS, const HeaderSearchOptions &HeaderSearchOpts, const PreprocessorOptions &PreprocessorOpts, const CodeGenOptions &CGO, llvm::LLVMContext &C, CoverageSourceInfo *CoverageInfo=nullptr)
CreateLLVMCodeGen - Create a CodeGenerator instance.
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
@ Module
Module linkage, which indicates that the entity can be referred to from other translation units withi...
Definition Linkage.h:54
@ Result
The result type of a method or function.
Definition TypeBase.h:905