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