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

source code of clang/lib/CIR/CodeGen/CIRGenModule.h