Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/lib/CIR/CodeGen/CIRGenModule.h
213799 views
1
//===--- CIRGenModule.h - Per-Module state for CIR gen ----------*- C++ -*-===//
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 is the internal per-translation-unit state used for CIR translation.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#ifndef LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENMODULE_H
14
#define LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENMODULE_H
15
16
#include "CIRGenBuilder.h"
17
#include "CIRGenCall.h"
18
#include "CIRGenTypeCache.h"
19
#include "CIRGenTypes.h"
20
#include "CIRGenValue.h"
21
22
#include "clang/AST/CharUnits.h"
23
#include "clang/CIR/Dialect/IR/CIRDataLayout.h"
24
#include "clang/CIR/Dialect/IR/CIRDialect.h"
25
26
#include "TargetInfo.h"
27
#include "mlir/IR/Builders.h"
28
#include "mlir/IR/BuiltinOps.h"
29
#include "mlir/IR/MLIRContext.h"
30
#include "clang/AST/Decl.h"
31
#include "clang/Basic/SourceManager.h"
32
#include "clang/Basic/TargetInfo.h"
33
#include "clang/CIR/Dialect/IR/CIROpsEnums.h"
34
#include "llvm/ADT/StringRef.h"
35
#include "llvm/TargetParser/Triple.h"
36
37
namespace clang {
38
class ASTContext;
39
class CodeGenOptions;
40
class Decl;
41
class GlobalDecl;
42
class LangOptions;
43
class TargetInfo;
44
class VarDecl;
45
46
namespace CIRGen {
47
48
class CIRGenFunction;
49
class CIRGenCXXABI;
50
51
enum ForDefinition_t : bool { NotForDefinition = false, ForDefinition = true };
52
53
/// This class organizes the cross-function state that is used while generating
54
/// CIR code.
55
class CIRGenModule : public CIRGenTypeCache {
56
CIRGenModule(CIRGenModule &) = delete;
57
CIRGenModule &operator=(CIRGenModule &) = delete;
58
59
public:
60
CIRGenModule(mlir::MLIRContext &mlirContext, clang::ASTContext &astContext,
61
const clang::CodeGenOptions &cgo,
62
clang::DiagnosticsEngine &diags);
63
64
~CIRGenModule();
65
66
private:
67
mutable std::unique_ptr<TargetCIRGenInfo> theTargetCIRGenInfo;
68
69
CIRGenBuilderTy builder;
70
71
/// Hold Clang AST information.
72
clang::ASTContext &astContext;
73
74
const clang::LangOptions &langOpts;
75
76
const clang::CodeGenOptions &codeGenOpts;
77
78
/// A "module" matches a c/cpp source file: containing a list of functions.
79
mlir::ModuleOp theModule;
80
81
clang::DiagnosticsEngine &diags;
82
83
const clang::TargetInfo &target;
84
85
std::unique_ptr<CIRGenCXXABI> abi;
86
87
CIRGenTypes genTypes;
88
89
/// Per-function codegen information. Updated everytime emitCIR is called
90
/// for FunctionDecls's.
91
CIRGenFunction *curCGF = nullptr;
92
93
public:
94
mlir::ModuleOp getModule() const { return theModule; }
95
CIRGenBuilderTy &getBuilder() { return builder; }
96
clang::ASTContext &getASTContext() const { return astContext; }
97
const clang::TargetInfo &getTarget() const { return target; }
98
const clang::CodeGenOptions &getCodeGenOpts() const { return codeGenOpts; }
99
CIRGenTypes &getTypes() { return genTypes; }
100
const clang::LangOptions &getLangOpts() const { return langOpts; }
101
102
CIRGenCXXABI &getCXXABI() const { return *abi; }
103
mlir::MLIRContext &getMLIRContext() { return *builder.getContext(); }
104
105
const cir::CIRDataLayout getDataLayout() const {
106
// FIXME(cir): instead of creating a CIRDataLayout every time, set it as an
107
// attribute for the CIRModule class.
108
return cir::CIRDataLayout(theModule);
109
}
110
111
/// -------
112
/// Handling globals
113
/// -------
114
115
mlir::Operation *lastGlobalOp = nullptr;
116
117
llvm::DenseMap<const Decl *, cir::GlobalOp> staticLocalDeclMap;
118
119
mlir::Operation *getGlobalValue(llvm::StringRef ref);
120
121
cir::GlobalOp getStaticLocalDeclAddress(const VarDecl *d) {
122
return staticLocalDeclMap[d];
123
}
124
125
void setStaticLocalDeclAddress(const VarDecl *d, cir::GlobalOp c) {
126
staticLocalDeclMap[d] = c;
127
}
128
129
cir::GlobalOp getOrCreateStaticVarDecl(const VarDecl &d,
130
cir::GlobalLinkageKind linkage);
131
132
/// If the specified mangled name is not in the module, create and return an
133
/// mlir::GlobalOp value
134
cir::GlobalOp getOrCreateCIRGlobal(llvm::StringRef mangledName, mlir::Type ty,
135
LangAS langAS, const VarDecl *d,
136
ForDefinition_t isForDefinition);
137
138
cir::GlobalOp getOrCreateCIRGlobal(const VarDecl *d, mlir::Type ty,
139
ForDefinition_t isForDefinition);
140
141
static cir::GlobalOp createGlobalOp(CIRGenModule &cgm, mlir::Location loc,
142
llvm::StringRef name, mlir::Type t,
143
mlir::Operation *insertPoint = nullptr);
144
145
llvm::StringMap<unsigned> cgGlobalNames;
146
std::string getUniqueGlobalName(const std::string &baseName);
147
148
/// Return the mlir::Value for the address of the given global variable.
149
/// If Ty is non-null and if the global doesn't exist, then it will be created
150
/// with the specified type instead of whatever the normal requested type
151
/// would be. If IsForDefinition is true, it is guaranteed that an actual
152
/// global with type Ty will be returned, not conversion of a variable with
153
/// the same mangled name but some other type.
154
mlir::Value
155
getAddrOfGlobalVar(const VarDecl *d, mlir::Type ty = {},
156
ForDefinition_t isForDefinition = NotForDefinition);
157
158
CharUnits computeNonVirtualBaseClassOffset(
159
const CXXRecordDecl *derivedClass,
160
llvm::iterator_range<CastExpr::path_const_iterator> path);
161
162
/// Get the CIR attributes and calling convention to use for a particular
163
/// function type.
164
///
165
/// \param calleeInfo - The callee information these attributes are being
166
/// constructed for. If valid, the attributes applied to this decl may
167
/// contribute to the function attributes and calling convention.
168
void constructAttributeList(CIRGenCalleeInfo calleeInfo,
169
mlir::NamedAttrList &attrs);
170
171
/// Return a constant array for the given string.
172
mlir::Attribute getConstantArrayFromStringLiteral(const StringLiteral *e);
173
174
/// Return a global symbol reference to a constant array for the given string
175
/// literal.
176
cir::GlobalOp getGlobalForStringLiteral(const StringLiteral *s,
177
llvm::StringRef name = ".str");
178
179
/// Set attributes which are common to any form of a global definition (alias,
180
/// Objective-C method, function, global variable).
181
///
182
/// NOTE: This should only be called for definitions.
183
void setCommonAttributes(GlobalDecl gd, mlir::Operation *op);
184
185
const TargetCIRGenInfo &getTargetCIRGenInfo();
186
187
/// Helpers to convert the presumed location of Clang's SourceLocation to an
188
/// MLIR Location.
189
mlir::Location getLoc(clang::SourceLocation cLoc);
190
mlir::Location getLoc(clang::SourceRange cRange);
191
192
/// Return the best known alignment for an unknown pointer to a
193
/// particular class.
194
clang::CharUnits getClassPointerAlignment(const clang::CXXRecordDecl *rd);
195
196
/// FIXME: this could likely be a common helper and not necessarily related
197
/// with codegen.
198
clang::CharUnits getNaturalTypeAlignment(clang::QualType t,
199
LValueBaseInfo *baseInfo);
200
201
cir::FuncOp
202
getAddrOfCXXStructor(clang::GlobalDecl gd,
203
const CIRGenFunctionInfo *fnInfo = nullptr,
204
cir::FuncType fnType = nullptr, bool dontDefer = false,
205
ForDefinition_t isForDefinition = NotForDefinition) {
206
return getAddrAndTypeOfCXXStructor(gd, fnInfo, fnType, dontDefer,
207
isForDefinition)
208
.second;
209
}
210
211
std::pair<cir::FuncType, cir::FuncOp> getAddrAndTypeOfCXXStructor(
212
clang::GlobalDecl gd, const CIRGenFunctionInfo *fnInfo = nullptr,
213
cir::FuncType fnType = nullptr, bool dontDefer = false,
214
ForDefinition_t isForDefinition = NotForDefinition);
215
216
/// This contains all the decls which have definitions but which are deferred
217
/// for emission and therefore should only be output if they are actually
218
/// used. If a decl is in this, then it is known to have not been referenced
219
/// yet.
220
std::map<llvm::StringRef, clang::GlobalDecl> deferredDecls;
221
222
// This is a list of deferred decls which we have seen that *are* actually
223
// referenced. These get code generated when the module is done.
224
std::vector<clang::GlobalDecl> deferredDeclsToEmit;
225
void addDeferredDeclToEmit(clang::GlobalDecl GD) {
226
deferredDeclsToEmit.emplace_back(GD);
227
}
228
229
void emitTopLevelDecl(clang::Decl *decl);
230
231
/// Determine whether the definition must be emitted; if this returns \c
232
/// false, the definition can be emitted lazily if it's used.
233
bool mustBeEmitted(const clang::ValueDecl *d);
234
235
/// Determine whether the definition can be emitted eagerly, or should be
236
/// delayed until the end of the translation unit. This is relevant for
237
/// definitions whose linkage can change, e.g. implicit function
238
/// instantiations which may later be explicitly instantiated.
239
bool mayBeEmittedEagerly(const clang::ValueDecl *d);
240
241
bool verifyModule() const;
242
243
/// Return the address of the given function. If funcType is non-null, then
244
/// this function will use the specified type if it has to create it.
245
// TODO: this is a bit weird as `GetAddr` given we give back a FuncOp?
246
cir::FuncOp
247
getAddrOfFunction(clang::GlobalDecl gd, mlir::Type funcType = nullptr,
248
bool forVTable = false, bool dontDefer = false,
249
ForDefinition_t isForDefinition = NotForDefinition);
250
251
mlir::Operation *
252
getAddrOfGlobal(clang::GlobalDecl gd,
253
ForDefinition_t isForDefinition = NotForDefinition);
254
255
/// Emit code for a single global function or variable declaration. Forward
256
/// declarations are emitted lazily.
257
void emitGlobal(clang::GlobalDecl gd);
258
259
void emitAliasForGlobal(llvm::StringRef mangledName, mlir::Operation *op,
260
GlobalDecl aliasGD, cir::FuncOp aliasee,
261
cir::GlobalLinkageKind linkage);
262
263
mlir::Type convertType(clang::QualType type);
264
265
/// Set the visibility for the given global.
266
void setGlobalVisibility(mlir::Operation *op, const NamedDecl *d) const;
267
void setDSOLocal(mlir::Operation *op) const;
268
void setDSOLocal(cir::CIRGlobalValueInterface gv) const;
269
270
/// Set visibility, dllimport/dllexport and dso_local.
271
/// This must be called after dllimport/dllexport is set.
272
void setGVProperties(mlir::Operation *op, const NamedDecl *d) const;
273
void setGVPropertiesAux(mlir::Operation *op, const NamedDecl *d) const;
274
275
/// Set function attributes for a function declaration.
276
void setFunctionAttributes(GlobalDecl gd, cir::FuncOp f,
277
bool isIncompleteFunction, bool isThunk);
278
279
void emitGlobalDefinition(clang::GlobalDecl gd,
280
mlir::Operation *op = nullptr);
281
void emitGlobalFunctionDefinition(clang::GlobalDecl gd, mlir::Operation *op);
282
void emitGlobalVarDefinition(const clang::VarDecl *vd,
283
bool isTentative = false);
284
285
void emitGlobalOpenACCDecl(const clang::OpenACCConstructDecl *cd);
286
287
// C++ related functions.
288
void emitDeclContext(const DeclContext *dc);
289
290
/// Return the result of value-initializing the given type, i.e. a null
291
/// expression of the given type.
292
mlir::Value emitNullConstant(QualType t, mlir::Location loc);
293
294
llvm::StringRef getMangledName(clang::GlobalDecl gd);
295
296
void emitTentativeDefinition(const VarDecl *d);
297
298
// Make sure that this type is translated.
299
void updateCompletedType(const clang::TagDecl *td);
300
301
// Produce code for this constructor/destructor. This method doesn't try to
302
// apply any ABI rules about which other constructors/destructors are needed
303
// or if they are alias to each other.
304
cir::FuncOp codegenCXXStructor(clang::GlobalDecl gd);
305
306
bool supportsCOMDAT() const;
307
void maybeSetTrivialComdat(const clang::Decl &d, mlir::Operation *op);
308
309
static void setInitializer(cir::GlobalOp &op, mlir::Attribute value);
310
311
cir::FuncOp
312
getOrCreateCIRFunction(llvm::StringRef mangledName, mlir::Type funcType,
313
clang::GlobalDecl gd, bool forVTable,
314
bool dontDefer = false, bool isThunk = false,
315
ForDefinition_t isForDefinition = NotForDefinition,
316
mlir::ArrayAttr extraAttrs = {});
317
318
cir::FuncOp createCIRFunction(mlir::Location loc, llvm::StringRef name,
319
cir::FuncType funcType,
320
const clang::FunctionDecl *funcDecl);
321
322
/// Given a builtin id for a function like "__builtin_fabsf", return a
323
/// Function* for "fabsf".
324
cir::FuncOp getBuiltinLibFunction(const FunctionDecl *fd, unsigned builtinID);
325
326
mlir::IntegerAttr getSize(CharUnits size) {
327
return builder.getSizeFromCharUnits(size);
328
}
329
330
/// Emit any needed decls for which code generation was deferred.
331
void emitDeferred();
332
333
/// Helper for `emitDeferred` to apply actual codegen.
334
void emitGlobalDecl(const clang::GlobalDecl &d);
335
336
const llvm::Triple &getTriple() const { return target.getTriple(); }
337
338
// Finalize CIR code generation.
339
void release();
340
341
/// -------
342
/// Visibility and Linkage
343
/// -------
344
345
static mlir::SymbolTable::Visibility
346
getMLIRVisibilityFromCIRLinkage(cir::GlobalLinkageKind GLK);
347
static cir::VisibilityKind getGlobalVisibilityKindFromClangVisibility(
348
clang::VisibilityAttr::VisibilityType visibility);
349
cir::VisibilityAttr getGlobalVisibilityAttrFromDecl(const Decl *decl);
350
static mlir::SymbolTable::Visibility getMLIRVisibility(cir::GlobalOp op);
351
cir::GlobalLinkageKind getFunctionLinkage(GlobalDecl gd);
352
cir::GlobalLinkageKind getCIRLinkageForDeclarator(const DeclaratorDecl *dd,
353
GVALinkage linkage,
354
bool isConstantVariable);
355
void setFunctionLinkage(GlobalDecl gd, cir::FuncOp f) {
356
cir::GlobalLinkageKind l = getFunctionLinkage(gd);
357
f.setLinkageAttr(cir::GlobalLinkageKindAttr::get(&getMLIRContext(), l));
358
mlir::SymbolTable::setSymbolVisibility(f,
359
getMLIRVisibilityFromCIRLinkage(l));
360
}
361
362
cir::GlobalLinkageKind getCIRLinkageVarDefinition(const VarDecl *vd,
363
bool isConstant);
364
365
void addReplacement(llvm::StringRef name, mlir::Operation *op);
366
367
/// Helpers to emit "not yet implemented" error diagnostics
368
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef);
369
370
template <typename T>
371
DiagnosticBuilder errorNYI(SourceLocation loc, llvm::StringRef feature,
372
const T &name) {
373
unsigned diagID =
374
diags.getCustomDiagID(DiagnosticsEngine::Error,
375
"ClangIR code gen Not Yet Implemented: %0: %1");
376
return diags.Report(loc, diagID) << feature << name;
377
}
378
379
DiagnosticBuilder errorNYI(mlir::Location loc, llvm::StringRef feature) {
380
// TODO: Convert the location to a SourceLocation
381
unsigned diagID = diags.getCustomDiagID(
382
DiagnosticsEngine::Error, "ClangIR code gen Not Yet Implemented: %0");
383
return diags.Report(diagID) << feature;
384
}
385
386
DiagnosticBuilder errorNYI(llvm::StringRef feature) const {
387
// TODO: Make a default location? currSrcLoc?
388
unsigned diagID = diags.getCustomDiagID(
389
DiagnosticsEngine::Error, "ClangIR code gen Not Yet Implemented: %0");
390
return diags.Report(diagID) << feature;
391
}
392
393
DiagnosticBuilder errorNYI(SourceRange, llvm::StringRef);
394
395
template <typename T>
396
DiagnosticBuilder errorNYI(SourceRange loc, llvm::StringRef feature,
397
const T &name) {
398
return errorNYI(loc.getBegin(), feature, name) << loc;
399
}
400
401
private:
402
// An ordered map of canonical GlobalDecls to their mangled names.
403
llvm::MapVector<clang::GlobalDecl, llvm::StringRef> mangledDeclNames;
404
llvm::StringMap<clang::GlobalDecl, llvm::BumpPtrAllocator> manglings;
405
406
// FIXME: should we use llvm::TrackingVH<mlir::Operation> here?
407
typedef llvm::StringMap<mlir::Operation *> ReplacementsTy;
408
ReplacementsTy replacements;
409
/// Call replaceAllUsesWith on all pairs in replacements.
410
void applyReplacements();
411
412
/// A helper function to replace all uses of OldF to NewF that replace
413
/// the type of pointer arguments. This is not needed to tradtional
414
/// pipeline since LLVM has opaque pointers but CIR not.
415
void replacePointerTypeArgs(cir::FuncOp oldF, cir::FuncOp newF);
416
417
void setNonAliasAttributes(GlobalDecl gd, mlir::Operation *op);
418
};
419
} // namespace CIRGen
420
421
} // namespace clang
422
423
#endif // LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENMODULE_H
424
425