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
37namespace clang {
38class ASTContext;
39class CodeGenOptions;
40class Decl;
41class GlobalDecl;
42class LangOptions;
43class TargetInfo;
44class VarDecl;
45
46namespace CIRGen {
47
48class CIRGenFunction;
49class CIRGenCXXABI;
50
51enum ForDefinition_t : bool { NotForDefinition = false, ForDefinition = true };
52
53/// This class organizes the cross-function state that is used while generating
54/// CIR code.
55class CIRGenModule : public CIRGenTypeCache {
56 CIRGenModule(CIRGenModule &) = delete;
57 CIRGenModule &operator=(CIRGenModule &) = delete;
58
59public:
60 CIRGenModule(mlir::MLIRContext &mlirContext, clang::ASTContext &astContext,
61 const clang::CodeGenOptions &cgo,
62 clang::DiagnosticsEngine &diags);
63
64 ~CIRGenModule();
65
66private:
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
93public:
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(args&: 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(L: DiagnosticsEngine::Error,
375 FormatString: "ClangIR code gen Not Yet Implemented: %0: %1");
376 return diags.Report(Loc: loc, DiagID: 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 L: DiagnosticsEngine::Error, FormatString: "ClangIR code gen Not Yet Implemented: %0");
383 return diags.Report(DiagID: diagID) << feature;
384 }
385
386 DiagnosticBuilder errorNYI(llvm::StringRef feature) const {
387 // TODO: Make a default location? currSrcLoc?
388 unsigned diagID = diags.getCustomDiagID(
389 L: DiagnosticsEngine::Error, FormatString: "ClangIR code gen Not Yet Implemented: %0");
390 return diags.Report(DiagID: 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
401private:
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

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