xref: /freebsd/contrib/llvm-project/clang/lib/CIR/CodeGen/CIRGenFunction.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===----------------------------------------------------------------------===//
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 // Internal per-function state used for AST-to-ClangIR code gen
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef CLANG_LIB_CIR_CODEGEN_CIRGENFUNCTION_H
14 #define CLANG_LIB_CIR_CODEGEN_CIRGENFUNCTION_H
15 
16 #include "CIRGenBuilder.h"
17 #include "CIRGenCall.h"
18 #include "CIRGenModule.h"
19 #include "CIRGenTypeCache.h"
20 #include "CIRGenValue.h"
21 
22 #include "Address.h"
23 
24 #include "clang/AST/ASTContext.h"
25 #include "clang/AST/CharUnits.h"
26 #include "clang/AST/Decl.h"
27 #include "clang/AST/Stmt.h"
28 #include "clang/AST/Type.h"
29 #include "clang/CIR/Dialect/IR/CIRDialect.h"
30 #include "clang/CIR/MissingFeatures.h"
31 #include "clang/CIR/TypeEvaluationKind.h"
32 
33 namespace {
34 class ScalarExprEmitter;
35 } // namespace
36 
37 namespace mlir {
38 namespace acc {
39 class LoopOp;
40 } // namespace acc
41 } // namespace mlir
42 
43 namespace clang::CIRGen {
44 
45 class CIRGenFunction : public CIRGenTypeCache {
46 public:
47   CIRGenModule &cgm;
48 
49 private:
50   friend class ::ScalarExprEmitter;
51   /// The builder is a helper class to create IR inside a function. The
52   /// builder is stateful, in particular it keeps an "insertion point": this
53   /// is where the next operations will be introduced.
54   CIRGenBuilderTy &builder;
55 
56 public:
57   /// The GlobalDecl for the current function being compiled or the global
58   /// variable currently being initialized.
59   clang::GlobalDecl curGD;
60 
61   /// The compiler-generated variable that holds the return value.
62   std::optional<mlir::Value> fnRetAlloca;
63 
64   /// CXXThisDecl - When generating code for a C++ member function,
65   /// this will hold the implicit 'this' declaration.
66   ImplicitParamDecl *cxxabiThisDecl = nullptr;
67   mlir::Value cxxabiThisValue = nullptr;
68   mlir::Value cxxThisValue = nullptr;
69   clang::CharUnits cxxThisAlignment;
70 
71   /// The value of 'this' to sue when evaluating CXXDefaultInitExprs within this
72   /// expression.
73   Address cxxDefaultInitExprThis = Address::invalid();
74 
75   // Holds the Decl for the current outermost non-closure context
76   const clang::Decl *curFuncDecl = nullptr;
77 
78   /// The function for which code is currently being generated.
79   cir::FuncOp curFn;
80 
81   using DeclMapTy = llvm::DenseMap<const clang::Decl *, Address>;
82   /// This keeps track of the CIR allocas or globals for local C
83   /// declarations.
84   DeclMapTy localDeclMap;
85 
86   /// The type of the condition for the emitting switch statement.
87   llvm::SmallVector<mlir::Type, 2> condTypeStack;
88 
getContext()89   clang::ASTContext &getContext() const { return cgm.getASTContext(); }
90 
getBuilder()91   CIRGenBuilderTy &getBuilder() { return builder; }
92 
getCIRGenModule()93   CIRGenModule &getCIRGenModule() { return cgm; }
getCIRGenModule()94   const CIRGenModule &getCIRGenModule() const { return cgm; }
95 
getCurFunctionEntryBlock()96   mlir::Block *getCurFunctionEntryBlock() { return &curFn.getRegion().front(); }
97 
98   /// Sanitizers enabled for this function.
99   clang::SanitizerSet sanOpts;
100 
101   /// Whether or not a Microsoft-style asm block has been processed within
102   /// this fuction. These can potentially set the return value.
103   bool sawAsmBlock = false;
104 
105   mlir::Type convertTypeForMem(QualType t);
106 
107   mlir::Type convertType(clang::QualType t);
convertType(const TypeDecl * t)108   mlir::Type convertType(const TypeDecl *t) {
109     return convertType(getContext().getTypeDeclType(t));
110   }
111 
112   ///  Return the cir::TypeEvaluationKind of QualType \c type.
113   static cir::TypeEvaluationKind getEvaluationKind(clang::QualType type);
114 
hasScalarEvaluationKind(clang::QualType type)115   static bool hasScalarEvaluationKind(clang::QualType type) {
116     return getEvaluationKind(type) == cir::TEK_Scalar;
117   }
118 
hasAggregateEvaluationKind(clang::QualType type)119   static bool hasAggregateEvaluationKind(clang::QualType type) {
120     return getEvaluationKind(type) == cir::TEK_Aggregate;
121   }
122 
123   CIRGenFunction(CIRGenModule &cgm, CIRGenBuilderTy &builder,
124                  bool suppressNewContext = false);
125   ~CIRGenFunction();
126 
getTypes()127   CIRGenTypes &getTypes() const { return cgm.getTypes(); }
128 
getTarget()129   const TargetInfo &getTarget() const { return cgm.getTarget(); }
getMLIRContext()130   mlir::MLIRContext &getMLIRContext() { return cgm.getMLIRContext(); }
131 
132   // ---------------------
133   // Opaque value handling
134   // ---------------------
135 
136   /// Keeps track of the current set of opaque value expressions.
137   llvm::DenseMap<const OpaqueValueExpr *, LValue> opaqueLValues;
138   llvm::DenseMap<const OpaqueValueExpr *, RValue> opaqueRValues;
139 
140 public:
141   /// A non-RAII class containing all the information about a bound
142   /// opaque value.  OpaqueValueMapping, below, is a RAII wrapper for
143   /// this which makes individual mappings very simple; using this
144   /// class directly is useful when you have a variable number of
145   /// opaque values or don't want the RAII functionality for some
146   /// reason.
147   class OpaqueValueMappingData {
148     const OpaqueValueExpr *opaqueValue;
149     bool boundLValue;
150 
OpaqueValueMappingData(const OpaqueValueExpr * ov,bool boundLValue)151     OpaqueValueMappingData(const OpaqueValueExpr *ov, bool boundLValue)
152         : opaqueValue(ov), boundLValue(boundLValue) {}
153 
154   public:
OpaqueValueMappingData()155     OpaqueValueMappingData() : opaqueValue(nullptr) {}
156 
shouldBindAsLValue(const Expr * expr)157     static bool shouldBindAsLValue(const Expr *expr) {
158       // gl-values should be bound as l-values for obvious reasons.
159       // Records should be bound as l-values because IR generation
160       // always keeps them in memory.  Expressions of function type
161       // act exactly like l-values but are formally required to be
162       // r-values in C.
163       return expr->isGLValue() || expr->getType()->isFunctionType() ||
164              hasAggregateEvaluationKind(expr->getType());
165     }
166 
167     static OpaqueValueMappingData
bind(CIRGenFunction & cgf,const OpaqueValueExpr * ov,const Expr * e)168     bind(CIRGenFunction &cgf, const OpaqueValueExpr *ov, const Expr *e) {
169       if (shouldBindAsLValue(ov))
170         return bind(cgf, ov, cgf.emitLValue(e));
171       return bind(cgf, ov, cgf.emitAnyExpr(e));
172     }
173 
174     static OpaqueValueMappingData
bind(CIRGenFunction & cgf,const OpaqueValueExpr * ov,const LValue & lv)175     bind(CIRGenFunction &cgf, const OpaqueValueExpr *ov, const LValue &lv) {
176       assert(shouldBindAsLValue(ov));
177       cgf.opaqueLValues.insert(std::make_pair(ov, lv));
178       return OpaqueValueMappingData(ov, true);
179     }
180 
181     static OpaqueValueMappingData
bind(CIRGenFunction & cgf,const OpaqueValueExpr * ov,const RValue & rv)182     bind(CIRGenFunction &cgf, const OpaqueValueExpr *ov, const RValue &rv) {
183       assert(!shouldBindAsLValue(ov));
184       cgf.opaqueRValues.insert(std::make_pair(ov, rv));
185 
186       OpaqueValueMappingData data(ov, false);
187 
188       // Work around an extremely aggressive peephole optimization in
189       // EmitScalarConversion which assumes that all other uses of a
190       // value are extant.
191       assert(!cir::MissingFeatures::peepholeProtection() && "NYI");
192       return data;
193     }
194 
isValid()195     bool isValid() const { return opaqueValue != nullptr; }
clear()196     void clear() { opaqueValue = nullptr; }
197 
unbind(CIRGenFunction & cgf)198     void unbind(CIRGenFunction &cgf) {
199       assert(opaqueValue && "no data to unbind!");
200 
201       if (boundLValue) {
202         cgf.opaqueLValues.erase(opaqueValue);
203       } else {
204         cgf.opaqueRValues.erase(opaqueValue);
205         assert(!cir::MissingFeatures::peepholeProtection() && "NYI");
206       }
207     }
208   };
209 
210   /// An RAII object to set (and then clear) a mapping for an OpaqueValueExpr.
211   class OpaqueValueMapping {
212     CIRGenFunction &cgf;
213     OpaqueValueMappingData data;
214 
215   public:
shouldBindAsLValue(const Expr * expr)216     static bool shouldBindAsLValue(const Expr *expr) {
217       return OpaqueValueMappingData::shouldBindAsLValue(expr);
218     }
219 
220     /// Build the opaque value mapping for the given conditional
221     /// operator if it's the GNU ?: extension.  This is a common
222     /// enough pattern that the convenience operator is really
223     /// helpful.
224     ///
OpaqueValueMapping(CIRGenFunction & cgf,const AbstractConditionalOperator * op)225     OpaqueValueMapping(CIRGenFunction &cgf,
226                        const AbstractConditionalOperator *op)
227         : cgf(cgf) {
228       if (mlir::isa<ConditionalOperator>(op))
229         // Leave Data empty.
230         return;
231 
232       const BinaryConditionalOperator *e =
233           mlir::cast<BinaryConditionalOperator>(op);
234       data = OpaqueValueMappingData::bind(cgf, e->getOpaqueValue(),
235                                           e->getCommon());
236     }
237 
238     /// Build the opaque value mapping for an OpaqueValueExpr whose source
239     /// expression is set to the expression the OVE represents.
OpaqueValueMapping(CIRGenFunction & cgf,const OpaqueValueExpr * ov)240     OpaqueValueMapping(CIRGenFunction &cgf, const OpaqueValueExpr *ov)
241         : cgf(cgf) {
242       if (ov) {
243         assert(ov->getSourceExpr() && "wrong form of OpaqueValueMapping used "
244                                       "for OVE with no source expression");
245         data = OpaqueValueMappingData::bind(cgf, ov, ov->getSourceExpr());
246       }
247     }
248 
OpaqueValueMapping(CIRGenFunction & cgf,const OpaqueValueExpr * opaqueValue,LValue lvalue)249     OpaqueValueMapping(CIRGenFunction &cgf, const OpaqueValueExpr *opaqueValue,
250                        LValue lvalue)
251         : cgf(cgf),
252           data(OpaqueValueMappingData::bind(cgf, opaqueValue, lvalue)) {}
253 
OpaqueValueMapping(CIRGenFunction & cgf,const OpaqueValueExpr * opaqueValue,RValue rvalue)254     OpaqueValueMapping(CIRGenFunction &cgf, const OpaqueValueExpr *opaqueValue,
255                        RValue rvalue)
256         : cgf(cgf),
257           data(OpaqueValueMappingData::bind(cgf, opaqueValue, rvalue)) {}
258 
pop()259     void pop() {
260       data.unbind(cgf);
261       data.clear();
262     }
263 
~OpaqueValueMapping()264     ~OpaqueValueMapping() {
265       if (data.isValid())
266         data.unbind(cgf);
267     }
268   };
269 
270 private:
271   /// Declare a variable in the current scope, return success if the variable
272   /// wasn't declared yet.
273   void declare(mlir::Value addrVal, const clang::Decl *var, clang::QualType ty,
274                mlir::Location loc, clang::CharUnits alignment,
275                bool isParam = false);
276 
277 public:
278   mlir::Value createDummyValue(mlir::Location loc, clang::QualType qt);
279 
280   void emitNullInitialization(mlir::Location loc, Address destPtr, QualType ty);
281 
282 private:
283   // Track current variable initialization (if there's one)
284   const clang::VarDecl *currVarDecl = nullptr;
285   class VarDeclContext {
286     CIRGenFunction &p;
287     const clang::VarDecl *oldVal = nullptr;
288 
289   public:
VarDeclContext(CIRGenFunction & p,const VarDecl * value)290     VarDeclContext(CIRGenFunction &p, const VarDecl *value) : p(p) {
291       if (p.currVarDecl)
292         oldVal = p.currVarDecl;
293       p.currVarDecl = value;
294     }
295 
296     /// Can be used to restore the state early, before the dtor
297     /// is run.
restore()298     void restore() { p.currVarDecl = oldVal; }
~VarDeclContext()299     ~VarDeclContext() { restore(); }
300   };
301 
302 public:
303   /// Use to track source locations across nested visitor traversals.
304   /// Always use a `SourceLocRAIIObject` to change currSrcLoc.
305   std::optional<mlir::Location> currSrcLoc;
306   class SourceLocRAIIObject {
307     CIRGenFunction &cgf;
308     std::optional<mlir::Location> oldLoc;
309 
310   public:
SourceLocRAIIObject(CIRGenFunction & cgf,mlir::Location value)311     SourceLocRAIIObject(CIRGenFunction &cgf, mlir::Location value) : cgf(cgf) {
312       if (cgf.currSrcLoc)
313         oldLoc = cgf.currSrcLoc;
314       cgf.currSrcLoc = value;
315     }
316 
317     /// Can be used to restore the state early, before the dtor
318     /// is run.
restore()319     void restore() { cgf.currSrcLoc = oldLoc; }
~SourceLocRAIIObject()320     ~SourceLocRAIIObject() { restore(); }
321   };
322 
323   /// Hold counters for incrementally naming temporaries
324   unsigned counterAggTmp = 0;
325   std::string getCounterAggTmpAsString();
326 
327   /// Helpers to convert Clang's SourceLocation to a MLIR Location.
328   mlir::Location getLoc(clang::SourceLocation srcLoc);
329   mlir::Location getLoc(clang::SourceRange srcLoc);
330   mlir::Location getLoc(mlir::Location lhs, mlir::Location rhs);
331 
getLangOpts()332   const clang::LangOptions &getLangOpts() const { return cgm.getLangOpts(); }
333 
334   // Wrapper for function prototype sources. Wraps either a FunctionProtoType or
335   // an ObjCMethodDecl.
336   struct PrototypeWrapper {
337     llvm::PointerUnion<const clang::FunctionProtoType *,
338                        const clang::ObjCMethodDecl *>
339         p;
340 
PrototypeWrapperPrototypeWrapper341     PrototypeWrapper(const clang::FunctionProtoType *ft) : p(ft) {}
PrototypeWrapperPrototypeWrapper342     PrototypeWrapper(const clang::ObjCMethodDecl *md) : p(md) {}
343   };
344 
345   bool isLValueSuitableForInlineAtomic(LValue lv);
346 
347   /// An abstract representation of regular/ObjC call/message targets.
348   class AbstractCallee {
349     /// The function declaration of the callee.
350     [[maybe_unused]] const clang::Decl *calleeDecl;
351 
352   public:
AbstractCallee()353     AbstractCallee() : calleeDecl(nullptr) {}
AbstractCallee(const clang::FunctionDecl * fd)354     AbstractCallee(const clang::FunctionDecl *fd) : calleeDecl(fd) {}
355 
hasFunctionDecl()356     bool hasFunctionDecl() const {
357       return llvm::isa_and_nonnull<clang::FunctionDecl>(calleeDecl);
358     }
359 
getNumParams()360     unsigned getNumParams() const {
361       if (const auto *fd = llvm::dyn_cast<clang::FunctionDecl>(calleeDecl))
362         return fd->getNumParams();
363       return llvm::cast<clang::ObjCMethodDecl>(calleeDecl)->param_size();
364     }
365 
getParamDecl(unsigned I)366     const clang::ParmVarDecl *getParamDecl(unsigned I) const {
367       if (const auto *fd = llvm::dyn_cast<clang::FunctionDecl>(calleeDecl))
368         return fd->getParamDecl(I);
369       return *(llvm::cast<clang::ObjCMethodDecl>(calleeDecl)->param_begin() +
370                I);
371     }
372   };
373 
374   void finishFunction(SourceLocation endLoc);
375 
376   /// Determine whether the given initializer is trivial in the sense
377   /// that it requires no code to be generated.
378   bool isTrivialInitializer(const Expr *init);
379 
380   /// If the specified expression does not fold to a constant, or if it does but
381   /// contains a label, return false.  If it constant folds return true and set
382   /// the boolean result in Result.
383   bool constantFoldsToBool(const clang::Expr *cond, bool &resultBool,
384                            bool allowLabels = false);
385   bool constantFoldsToSimpleInteger(const clang::Expr *cond,
386                                     llvm::APSInt &resultInt,
387                                     bool allowLabels = false);
388 
389   /// Return true if the statement contains a label in it.  If
390   /// this statement is not executed normally, it not containing a label means
391   /// that we can just remove the code.
392   bool containsLabel(const clang::Stmt *s, bool ignoreCaseStmts = false);
393 
394   class ConstantEmission {
395     // Cannot use mlir::TypedAttr directly here because of bit availability.
396     llvm::PointerIntPair<mlir::Attribute, 1, bool> valueAndIsReference;
ConstantEmission(mlir::TypedAttr c,bool isReference)397     ConstantEmission(mlir::TypedAttr c, bool isReference)
398         : valueAndIsReference(c, isReference) {}
399 
400   public:
ConstantEmission()401     ConstantEmission() {}
forReference(mlir::TypedAttr c)402     static ConstantEmission forReference(mlir::TypedAttr c) {
403       return ConstantEmission(c, true);
404     }
forValue(mlir::TypedAttr c)405     static ConstantEmission forValue(mlir::TypedAttr c) {
406       return ConstantEmission(c, false);
407     }
408 
409     explicit operator bool() const {
410       return valueAndIsReference.getOpaqueValue() != nullptr;
411     }
412 
isReference()413     bool isReference() const { return valueAndIsReference.getInt(); }
getReferenceLValue(CIRGenFunction & cgf,Expr * refExpr)414     LValue getReferenceLValue(CIRGenFunction &cgf, Expr *refExpr) const {
415       assert(isReference());
416       cgf.cgm.errorNYI(refExpr->getSourceRange(),
417                        "ConstantEmission::getReferenceLValue");
418       return {};
419     }
420 
getValue()421     mlir::TypedAttr getValue() const {
422       assert(!isReference());
423       return mlir::cast<mlir::TypedAttr>(valueAndIsReference.getPointer());
424     }
425   };
426 
427   ConstantEmission tryEmitAsConstant(DeclRefExpr *refExpr);
428 
429   struct AutoVarEmission {
430     const clang::VarDecl *Variable;
431     /// The address of the alloca for languages with explicit address space
432     /// (e.g. OpenCL) or alloca casted to generic pointer for address space
433     /// agnostic languages (e.g. C++). Invalid if the variable was emitted
434     /// as a global constant.
435     Address Addr;
436 
437     /// True if the variable is of aggregate type and has a constant
438     /// initializer.
439     bool IsConstantAggregate = false;
440 
441     /// True if the variable is a __block variable that is captured by an
442     /// escaping block.
443     bool IsEscapingByRef = false;
444 
445     mlir::Value NRVOFlag{};
446 
447     struct Invalid {};
AutoVarEmissionAutoVarEmission448     AutoVarEmission(Invalid) : Variable(nullptr), Addr(Address::invalid()) {}
449 
AutoVarEmissionAutoVarEmission450     AutoVarEmission(const clang::VarDecl &variable)
451         : Variable(&variable), Addr(Address::invalid()) {}
452 
invalidAutoVarEmission453     static AutoVarEmission invalid() { return AutoVarEmission(Invalid()); }
454 
wasEmittedAsGlobalAutoVarEmission455     bool wasEmittedAsGlobal() const { return !Addr.isValid(); }
456 
457     /// Returns the raw, allocated address, which is not necessarily
458     /// the address of the object itself. It is casted to default
459     /// address space for address space agnostic languages.
getAllocatedAddressAutoVarEmission460     Address getAllocatedAddress() const { return Addr; }
461 
462     /// Returns the address of the object within this declaration.
463     /// Note that this does not chase the forwarding pointer for
464     /// __block decls.
getObjectAddressAutoVarEmission465     Address getObjectAddress(CIRGenFunction &cgf) const {
466       if (!IsEscapingByRef)
467         return Addr;
468 
469       assert(!cir::MissingFeatures::opAllocaEscapeByReference());
470       return Address::invalid();
471     }
472   };
473 
474   /// Perform the usual unary conversions on the specified expression and
475   /// compare the result against zero, returning an Int1Ty value.
476   mlir::Value evaluateExprAsBool(const clang::Expr *e);
477 
478   cir::GlobalOp addInitializerToStaticVarDecl(const VarDecl &d,
479                                               cir::GlobalOp gv,
480                                               cir::GetGlobalOp gvAddr);
481 
482   /// Set the address of a local variable.
setAddrOfLocalVar(const clang::VarDecl * vd,Address addr)483   void setAddrOfLocalVar(const clang::VarDecl *vd, Address addr) {
484     assert(!localDeclMap.count(vd) && "Decl already exists in LocalDeclMap!");
485     localDeclMap.insert({vd, addr});
486     // TODO: Add symbol table support
487   }
488 
489   bool shouldNullCheckClassCastValue(const CastExpr *ce);
490 
491   RValue convertTempToRValue(Address addr, clang::QualType type,
492                              clang::SourceLocation loc);
493 
494   static bool
495   isConstructorDelegationValid(const clang::CXXConstructorDecl *ctor);
496 
497   /// A scope within which we are constructing the fields of an object which
498   /// might use a CXXDefaultInitExpr. This stashes away a 'this' value to use if
499   /// we need to evaluate the CXXDefaultInitExpr within the evaluation.
500   class FieldConstructionScope {
501   public:
FieldConstructionScope(CIRGenFunction & cgf,Address thisAddr)502     FieldConstructionScope(CIRGenFunction &cgf, Address thisAddr)
503         : cgf(cgf), oldCXXDefaultInitExprThis(cgf.cxxDefaultInitExprThis) {
504       cgf.cxxDefaultInitExprThis = thisAddr;
505     }
~FieldConstructionScope()506     ~FieldConstructionScope() {
507       cgf.cxxDefaultInitExprThis = oldCXXDefaultInitExprThis;
508     }
509 
510   private:
511     CIRGenFunction &cgf;
512     Address oldCXXDefaultInitExprThis;
513   };
514 
515   LValue makeNaturalAlignPointeeAddrLValue(mlir::Value v, clang::QualType t);
516   LValue makeNaturalAlignAddrLValue(mlir::Value val, QualType ty);
517 
518   /// Construct an address with the natural alignment of T. If a pointer to T
519   /// is expected to be signed, the pointer passed to this function must have
520   /// been signed, and the returned Address will have the pointer authentication
521   /// information needed to authenticate the signed pointer.
522   Address makeNaturalAddressForPointer(mlir::Value ptr, QualType t,
523                                        CharUnits alignment,
524                                        bool forPointeeType = false,
525                                        LValueBaseInfo *baseInfo = nullptr) {
526     if (alignment.isZero())
527       alignment = cgm.getNaturalTypeAlignment(t, baseInfo);
528     return Address(ptr, convertTypeForMem(t), alignment);
529   }
530 
531   Address getAddressOfBaseClass(
532       Address value, const CXXRecordDecl *derived,
533       llvm::iterator_range<CastExpr::path_const_iterator> path,
534       bool nullCheckValue, SourceLocation loc);
535 
536   LValue makeAddrLValue(Address addr, QualType ty,
537                         AlignmentSource source = AlignmentSource::Type) {
538     return makeAddrLValue(addr, ty, LValueBaseInfo(source));
539   }
540 
makeAddrLValue(Address addr,QualType ty,LValueBaseInfo baseInfo)541   LValue makeAddrLValue(Address addr, QualType ty, LValueBaseInfo baseInfo) {
542     return LValue::makeAddr(addr, ty, baseInfo);
543   }
544 
545   /// Return the address of a local variable.
getAddrOfLocalVar(const clang::VarDecl * vd)546   Address getAddrOfLocalVar(const clang::VarDecl *vd) {
547     auto it = localDeclMap.find(vd);
548     assert(it != localDeclMap.end() &&
549            "Invalid argument to getAddrOfLocalVar(), no decl!");
550     return it->second;
551   }
552 
553   Address getAddrOfBitFieldStorage(LValue base, const clang::FieldDecl *field,
554                                    mlir::Type fieldType, unsigned index);
555 
556   /// Load the value for 'this'. This function is only valid while generating
557   /// code for an C++ member function.
558   /// FIXME(cir): this should return a mlir::Value!
loadCXXThis()559   mlir::Value loadCXXThis() {
560     assert(cxxThisValue && "no 'this' value for this function");
561     return cxxThisValue;
562   }
563   Address loadCXXThisAddress();
564 
565   /// Convert the given pointer to a complete class to the given direct base.
566   Address getAddressOfDirectBaseInCompleteClass(mlir::Location loc,
567                                                 Address value,
568                                                 const CXXRecordDecl *derived,
569                                                 const CXXRecordDecl *base,
570                                                 bool baseIsVirtual);
571 
572   /// Determine whether a base class initialization may overlap some other
573   /// object.
574   AggValueSlot::Overlap_t getOverlapForBaseInit(const CXXRecordDecl *rd,
575                                                 const CXXRecordDecl *baseRD,
576                                                 bool isVirtual);
577 
578   /// Get an appropriate 'undef' rvalue for the given type.
579   /// TODO: What's the equivalent for MLIR? Currently we're only using this for
580   /// void types so it just returns RValue::get(nullptr) but it'll need
581   /// addressed later.
582   RValue getUndefRValue(clang::QualType ty);
583 
584   cir::FuncOp generateCode(clang::GlobalDecl gd, cir::FuncOp fn,
585                            cir::FuncType funcType);
586 
587   clang::QualType buildFunctionArgList(clang::GlobalDecl gd,
588                                        FunctionArgList &args);
589 
590   /// Emit code for the start of a function.
591   /// \param loc       The location to be associated with the function.
592   /// \param startLoc  The location of the function body.
593   void startFunction(clang::GlobalDecl gd, clang::QualType returnType,
594                      cir::FuncOp fn, cir::FuncType funcType,
595                      FunctionArgList args, clang::SourceLocation loc,
596                      clang::SourceLocation startLoc);
597 
598   /// Represents a scope, including function bodies, compound statements, and
599   /// the substatements of if/while/do/for/switch/try statements.  This class
600   /// handles any automatic cleanup, along with the return value.
601   struct LexicalScope {
602   private:
603     // TODO(CIR): This will live in the base class RunCleanupScope once that
604     // class is upstreamed.
605     CIRGenFunction &cgf;
606 
607     // Points to the scope entry block. This is useful, for instance, for
608     // helping to insert allocas before finalizing any recursive CodeGen from
609     // switches.
610     mlir::Block *entryBlock;
611 
612     LexicalScope *parentScope = nullptr;
613 
614     // Only Regular is used at the moment. Support for other kinds will be
615     // added as the relevant statements/expressions are upstreamed.
616     enum Kind {
617       Regular,   // cir.if, cir.scope, if_regions
618       Ternary,   // cir.ternary
619       Switch,    // cir.switch
620       Try,       // cir.try
621       GlobalInit // cir.global initialization code
622     };
623     Kind scopeKind = Kind::Regular;
624 
625     // The scope return value.
626     mlir::Value retVal = nullptr;
627 
628     mlir::Location beginLoc;
629     mlir::Location endLoc;
630 
631   public:
632     unsigned depth = 0;
633 
LexicalScopeLexicalScope634     LexicalScope(CIRGenFunction &cgf, mlir::Location loc, mlir::Block *eb)
635         : cgf(cgf), entryBlock(eb), parentScope(cgf.curLexScope), beginLoc(loc),
636           endLoc(loc) {
637 
638       assert(entryBlock && "LexicalScope requires an entry block");
639       cgf.curLexScope = this;
640       if (parentScope)
641         ++depth;
642 
643       if (const auto fusedLoc = mlir::dyn_cast<mlir::FusedLoc>(loc)) {
644         assert(fusedLoc.getLocations().size() == 2 && "too many locations");
645         beginLoc = fusedLoc.getLocations()[0];
646         endLoc = fusedLoc.getLocations()[1];
647       }
648     }
649 
setRetValLexicalScope650     void setRetVal(mlir::Value v) { retVal = v; }
651 
652     void cleanup();
restoreLexicalScope653     void restore() { cgf.curLexScope = parentScope; }
654 
~LexicalScopeLexicalScope655     ~LexicalScope() {
656       assert(!cir::MissingFeatures::generateDebugInfo());
657       cleanup();
658       restore();
659     }
660 
661     // ---
662     // Kind
663     // ---
isGlobalInitLexicalScope664     bool isGlobalInit() { return scopeKind == Kind::GlobalInit; }
isRegularLexicalScope665     bool isRegular() { return scopeKind == Kind::Regular; }
isSwitchLexicalScope666     bool isSwitch() { return scopeKind == Kind::Switch; }
isTernaryLexicalScope667     bool isTernary() { return scopeKind == Kind::Ternary; }
isTryLexicalScope668     bool isTry() { return scopeKind == Kind::Try; }
669 
setAsGlobalInitLexicalScope670     void setAsGlobalInit() { scopeKind = Kind::GlobalInit; }
setAsSwitchLexicalScope671     void setAsSwitch() { scopeKind = Kind::Switch; }
setAsTernaryLexicalScope672     void setAsTernary() { scopeKind = Kind::Ternary; }
673 
674     // ---
675     // Return handling.
676     // ---
677 
678   private:
679     // `returnBlock`, `returnLoc`, and all the functions that deal with them
680     // will change and become more complicated when `switch` statements are
681     // upstreamed.  `case` statements within the `switch` are in the same scope
682     // but have their own regions.  Therefore the LexicalScope will need to
683     // keep track of multiple return blocks.
684     mlir::Block *returnBlock = nullptr;
685     std::optional<mlir::Location> returnLoc;
686 
687     // See the comment on `getOrCreateRetBlock`.
createRetBlockLexicalScope688     mlir::Block *createRetBlock(CIRGenFunction &cgf, mlir::Location loc) {
689       assert(returnBlock == nullptr && "only one return block per scope");
690       // Create the cleanup block but don't hook it up just yet.
691       mlir::OpBuilder::InsertionGuard guard(cgf.builder);
692       returnBlock =
693           cgf.builder.createBlock(cgf.builder.getBlock()->getParent());
694       updateRetLoc(returnBlock, loc);
695       return returnBlock;
696     }
697 
698     cir::ReturnOp emitReturn(mlir::Location loc);
699     void emitImplicitReturn();
700 
701   public:
getRetBlockLexicalScope702     mlir::Block *getRetBlock() { return returnBlock; }
getRetLocLexicalScope703     mlir::Location getRetLoc(mlir::Block *b) { return *returnLoc; }
updateRetLocLexicalScope704     void updateRetLoc(mlir::Block *b, mlir::Location loc) { returnLoc = loc; }
705 
706     // Create the return block for this scope, or return the existing one.
707     // This get-or-create logic is necessary to handle multiple return
708     // statements within the same scope, which can happen if some of them are
709     // dead code or if there is a `goto` into the middle of the scope.
getOrCreateRetBlockLexicalScope710     mlir::Block *getOrCreateRetBlock(CIRGenFunction &cgf, mlir::Location loc) {
711       if (returnBlock == nullptr) {
712         returnBlock = createRetBlock(cgf, loc);
713         return returnBlock;
714       }
715       updateRetLoc(returnBlock, loc);
716       return returnBlock;
717     }
718 
getEntryBlockLexicalScope719     mlir::Block *getEntryBlock() { return entryBlock; }
720   };
721 
722   LexicalScope *curLexScope = nullptr;
723 
724   /// ----------------------
725   /// CIR emit functions
726   /// ----------------------
727 private:
728   void emitAndUpdateRetAlloca(clang::QualType type, mlir::Location loc,
729                               clang::CharUnits alignment);
730 
731   CIRGenCallee emitDirectCallee(const GlobalDecl &gd);
732 
733 public:
734   Address emitAddrOfFieldStorage(Address base, const FieldDecl *field,
735                                  llvm::StringRef fieldName,
736                                  unsigned fieldIndex);
737 
738   mlir::Value emitAlloca(llvm::StringRef name, mlir::Type ty,
739                          mlir::Location loc, clang::CharUnits alignment,
740                          bool insertIntoFnEntryBlock,
741                          mlir::Value arraySize = nullptr);
742   mlir::Value emitAlloca(llvm::StringRef name, mlir::Type ty,
743                          mlir::Location loc, clang::CharUnits alignment,
744                          mlir::OpBuilder::InsertPoint ip,
745                          mlir::Value arraySize = nullptr);
746 
747   void emitAggregateStore(mlir::Value value, Address dest);
748 
749   void emitAggExpr(const clang::Expr *e, AggValueSlot slot);
750 
751   LValue emitAggExprToLValue(const Expr *e);
752 
753   /// Emit code to compute the specified expression which can have any type. The
754   /// result is returned as an RValue struct. If this is an aggregate
755   /// expression, the aggloc/agglocvolatile arguments indicate where the result
756   /// should be returned.
757   RValue emitAnyExpr(const clang::Expr *e,
758                      AggValueSlot aggSlot = AggValueSlot::ignored());
759 
760   /// Similarly to emitAnyExpr(), however, the result will always be accessible
761   /// even if no aggregate location is provided.
762   RValue emitAnyExprToTemp(const clang::Expr *e);
763 
764   LValue emitArraySubscriptExpr(const clang::ArraySubscriptExpr *e);
765 
766   Address emitArrayToPointerDecay(const Expr *array);
767 
768   AutoVarEmission emitAutoVarAlloca(const clang::VarDecl &d);
769 
770   /// Emit code and set up symbol table for a variable declaration with auto,
771   /// register, or no storage class specifier. These turn into simple stack
772   /// objects, globals depending on target.
773   void emitAutoVarDecl(const clang::VarDecl &d);
774 
775   void emitAutoVarCleanups(const AutoVarEmission &emission);
776   void emitAutoVarInit(const AutoVarEmission &emission);
777 
778   void emitBaseInitializer(mlir::Location loc, const CXXRecordDecl *classDecl,
779                            CXXCtorInitializer *baseInit);
780 
781   LValue emitBinaryOperatorLValue(const BinaryOperator *e);
782 
783   mlir::LogicalResult emitBreakStmt(const clang::BreakStmt &s);
784 
785   RValue emitBuiltinExpr(const clang::GlobalDecl &gd, unsigned builtinID,
786                          const clang::CallExpr *e, ReturnValueSlot returnValue);
787 
788   RValue emitCall(const CIRGenFunctionInfo &funcInfo,
789                   const CIRGenCallee &callee, ReturnValueSlot returnValue,
790                   const CallArgList &args, cir::CIRCallOpInterface *callOp,
791                   mlir::Location loc);
792   RValue emitCall(const CIRGenFunctionInfo &funcInfo,
793                   const CIRGenCallee &callee, ReturnValueSlot returnValue,
794                   const CallArgList &args,
795                   cir::CIRCallOpInterface *callOrTryCall = nullptr) {
796     assert(currSrcLoc && "source location must have been set");
797     return emitCall(funcInfo, callee, returnValue, args, callOrTryCall,
798                     *currSrcLoc);
799   }
800 
801   RValue emitCall(clang::QualType calleeTy, const CIRGenCallee &callee,
802                   const clang::CallExpr *e, ReturnValueSlot returnValue);
803   void emitCallArg(CallArgList &args, const clang::Expr *e,
804                    clang::QualType argType);
805   void emitCallArgs(
806       CallArgList &args, PrototypeWrapper prototype,
807       llvm::iterator_range<clang::CallExpr::const_arg_iterator> argRange,
808       AbstractCallee callee = AbstractCallee(), unsigned paramsToSkip = 0);
809   RValue emitCallExpr(const clang::CallExpr *e,
810                       ReturnValueSlot returnValue = ReturnValueSlot());
811   LValue emitCallExprLValue(const clang::CallExpr *e);
812   CIRGenCallee emitCallee(const clang::Expr *e);
813 
814   template <typename T>
815   mlir::LogicalResult emitCaseDefaultCascade(const T *stmt, mlir::Type condType,
816                                              mlir::ArrayAttr value,
817                                              cir::CaseOpKind kind,
818                                              bool buildingTopLevelCase);
819 
820   mlir::LogicalResult emitCaseStmt(const clang::CaseStmt &s,
821                                    mlir::Type condType,
822                                    bool buildingTopLevelCase);
823 
824   LValue emitCastLValue(const CastExpr *e);
825 
826   /// Emits an argument for a call to a `__builtin_assume`. If the builtin
827   /// sanitizer is enabled, a runtime check is also emitted.
828   mlir::Value emitCheckedArgForAssume(const Expr *e);
829 
830   LValue emitCompoundAssignmentLValue(const clang::CompoundAssignOperator *e);
831 
832   void emitConstructorBody(FunctionArgList &args);
833   void emitDestructorBody(FunctionArgList &args);
834 
835   mlir::LogicalResult emitContinueStmt(const clang::ContinueStmt &s);
836 
837   void emitCXXConstructExpr(const clang::CXXConstructExpr *e,
838                             AggValueSlot dest);
839 
840   void emitCXXConstructorCall(const clang::CXXConstructorDecl *d,
841                               clang::CXXCtorType type, bool forVirtualBase,
842                               bool delegating, AggValueSlot thisAVS,
843                               const clang::CXXConstructExpr *e);
844 
845   void emitCXXConstructorCall(const clang::CXXConstructorDecl *d,
846                               clang::CXXCtorType type, bool forVirtualBase,
847                               bool delegating, Address thisAddr,
848                               CallArgList &args, clang::SourceLocation loc);
849 
850   mlir::LogicalResult emitCXXForRangeStmt(const CXXForRangeStmt &s,
851                                           llvm::ArrayRef<const Attr *> attrs);
852 
853   RValue emitCXXMemberCallExpr(const clang::CXXMemberCallExpr *e,
854                                ReturnValueSlot returnValue);
855 
856   RValue emitCXXMemberOrOperatorCall(
857       const clang::CXXMethodDecl *md, const CIRGenCallee &callee,
858       ReturnValueSlot returnValue, mlir::Value thisPtr,
859       mlir::Value implicitParam, clang::QualType implicitParamTy,
860       const clang::CallExpr *ce, CallArgList *rtlArgs);
861 
862   RValue emitCXXMemberOrOperatorMemberCallExpr(
863       const clang::CallExpr *ce, const clang::CXXMethodDecl *md,
864       ReturnValueSlot returnValue, bool hasQualifier,
865       clang::NestedNameSpecifier *qualifier, bool isArrow,
866       const clang::Expr *base);
867 
868   mlir::Value emitCXXNewExpr(const CXXNewExpr *e);
869 
870   RValue emitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *e,
871                                        const CXXMethodDecl *md,
872                                        ReturnValueSlot returnValue);
873 
874   void emitCtorPrologue(const clang::CXXConstructorDecl *ctor,
875                         clang::CXXCtorType ctorType, FunctionArgList &args);
876 
877   // It's important not to confuse this and emitDelegateCXXConstructorCall.
878   // Delegating constructors are the C++11 feature. The constructor delegate
879   // optimization is used to reduce duplication in the base and complete
880   // constructors where they are substantially the same.
881   void emitDelegatingCXXConstructorCall(const CXXConstructorDecl *ctor,
882                                         const FunctionArgList &args);
883 
884   mlir::LogicalResult emitDoStmt(const clang::DoStmt &s);
885 
886   /// Emit an expression as an initializer for an object (variable, field, etc.)
887   /// at the given location.  The expression is not necessarily the normal
888   /// initializer for the object, and the address is not necessarily
889   /// its normal location.
890   ///
891   /// \param init the initializing expression
892   /// \param d the object to act as if we're initializing
893   /// \param lvalue the lvalue to initialize
894   /// \param capturedByInit true if \p d is a __block variable whose address is
895   /// potentially changed by the initializer
896   void emitExprAsInit(const clang::Expr *init, const clang::ValueDecl *d,
897                       LValue lvalue, bool capturedByInit = false);
898 
899   mlir::LogicalResult emitFunctionBody(const clang::Stmt *body);
900 
901   void emitImplicitAssignmentOperatorBody(FunctionArgList &args);
902 
903   void emitInitializerForField(clang::FieldDecl *field, LValue lhs,
904                                clang::Expr *init);
905 
906   mlir::Value emitPromotedComplexExpr(const Expr *e, QualType promotionType);
907 
908   mlir::Value emitPromotedScalarExpr(const Expr *e, QualType promotionType);
909 
910   /// Emit the computation of the specified expression of scalar type.
911   mlir::Value emitScalarExpr(const clang::Expr *e);
912 
913   mlir::Value emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv,
914                                       bool isInc, bool isPre);
915 
916   /// Build a debug stoppoint if we are emitting debug info.
917   void emitStopPoint(const Stmt *s);
918 
919   // Build CIR for a statement. useCurrentScope should be true if no
920   // new scopes need be created when finding a compound statement.
921   mlir::LogicalResult emitStmt(const clang::Stmt *s, bool useCurrentScope,
922                                llvm::ArrayRef<const Attr *> attrs = {});
923 
924   mlir::LogicalResult emitSimpleStmt(const clang::Stmt *s,
925                                      bool useCurrentScope);
926 
927   mlir::LogicalResult emitForStmt(const clang::ForStmt &s);
928 
929   /// Emit the computation of the specified expression of complex type,
930   /// returning the result.
931   mlir::Value emitComplexExpr(const Expr *e);
932 
933   LValue emitComplexAssignmentLValue(const BinaryOperator *e);
934 
935   void emitCompoundStmt(const clang::CompoundStmt &s);
936 
937   void emitCompoundStmtWithoutScope(const clang::CompoundStmt &s);
938 
939   void emitDecl(const clang::Decl &d);
940   mlir::LogicalResult emitDeclStmt(const clang::DeclStmt &s);
941   LValue emitDeclRefLValue(const clang::DeclRefExpr *e);
942 
943   mlir::LogicalResult emitDefaultStmt(const clang::DefaultStmt &s,
944                                       mlir::Type condType,
945                                       bool buildingTopLevelCase);
946 
947   void emitDelegateCXXConstructorCall(const clang::CXXConstructorDecl *ctor,
948                                       clang::CXXCtorType ctorType,
949                                       const FunctionArgList &args,
950                                       clang::SourceLocation loc);
951 
952   /// We are performing a delegate call; that is, the current function is
953   /// delegating to another one. Produce a r-value suitable for passing the
954   /// given parameter.
955   void emitDelegateCallArg(CallArgList &args, const clang::VarDecl *param,
956                            clang::SourceLocation loc);
957 
958   /// Emit an `if` on a boolean condition to the specified blocks.
959   /// FIXME: Based on the condition, this might try to simplify the codegen of
960   /// the conditional based on the branch.
961   /// In the future, we may apply code generation simplifications here,
962   /// similar to those used in classic LLVM  codegen
963   /// See `EmitBranchOnBoolExpr` for inspiration.
964   mlir::LogicalResult emitIfOnBoolExpr(const clang::Expr *cond,
965                                        const clang::Stmt *thenS,
966                                        const clang::Stmt *elseS);
967   cir::IfOp emitIfOnBoolExpr(const clang::Expr *cond,
968                              BuilderCallbackRef thenBuilder,
969                              mlir::Location thenLoc,
970                              BuilderCallbackRef elseBuilder,
971                              std::optional<mlir::Location> elseLoc = {});
972 
973   mlir::Value emitOpOnBoolExpr(mlir::Location loc, const clang::Expr *cond);
974 
975   mlir::LogicalResult emitIfStmt(const clang::IfStmt &s);
976 
977   /// Emit code to compute the specified expression,
978   /// ignoring the result.
979   void emitIgnoredExpr(const clang::Expr *e);
980 
981   RValue emitLoadOfBitfieldLValue(LValue lv, SourceLocation loc);
982 
983   /// Given an expression that represents a value lvalue, this method emits
984   /// the address of the lvalue, then loads the result as an rvalue,
985   /// returning the rvalue.
986   RValue emitLoadOfLValue(LValue lv, SourceLocation loc);
987 
988   Address emitLoadOfReference(LValue refLVal, mlir::Location loc,
989                               LValueBaseInfo *pointeeBaseInfo);
990   LValue emitLoadOfReferenceLValue(Address refAddr, mlir::Location loc,
991                                    QualType refTy, AlignmentSource source);
992 
993   /// EmitLoadOfScalar - Load a scalar value from an address, taking
994   /// care to appropriately convert from the memory representation to
995   /// the LLVM value representation.  The l-value must be a simple
996   /// l-value.
997   mlir::Value emitLoadOfScalar(LValue lvalue, SourceLocation loc);
998 
999   /// Emit code to compute a designator that specifies the location
1000   /// of the expression.
1001   /// FIXME: document this function better.
1002   LValue emitLValue(const clang::Expr *e);
1003   LValue emitLValueForBitField(LValue base, const FieldDecl *field);
1004   LValue emitLValueForField(LValue base, const clang::FieldDecl *field);
1005 
1006   /// Like emitLValueForField, excpet that if the Field is a reference, this
1007   /// will return the address of the reference and not the address of the value
1008   /// stored in the reference.
1009   LValue emitLValueForFieldInitialization(LValue base,
1010                                           const clang::FieldDecl *field,
1011                                           llvm::StringRef fieldName);
1012 
1013   LValue emitMemberExpr(const MemberExpr *e);
1014 
1015   /// Given an expression with a pointer type, emit the value and compute our
1016   /// best estimate of the alignment of the pointee.
1017   ///
1018   /// One reasonable way to use this information is when there's a language
1019   /// guarantee that the pointer must be aligned to some stricter value, and
1020   /// we're simply trying to ensure that sufficiently obvious uses of under-
1021   /// aligned objects don't get miscompiled; for example, a placement new
1022   /// into the address of a local variable.  In such a case, it's quite
1023   /// reasonable to just ignore the returned alignment when it isn't from an
1024   /// explicit source.
1025   Address emitPointerWithAlignment(const clang::Expr *expr,
1026                                    LValueBaseInfo *baseInfo);
1027 
1028   /// Emits a reference binding to the passed in expression.
1029   RValue emitReferenceBindingToExpr(const Expr *e);
1030 
1031   mlir::LogicalResult emitReturnStmt(const clang::ReturnStmt &s);
1032 
1033   mlir::Value emitScalarConstant(const ConstantEmission &constant, Expr *e);
1034 
1035   /// Emit a conversion from the specified type to the specified destination
1036   /// type, both of which are CIR scalar types.
1037   mlir::Value emitScalarConversion(mlir::Value src, clang::QualType srcType,
1038                                    clang::QualType dstType,
1039                                    clang::SourceLocation loc);
1040 
1041   void emitScalarInit(const clang::Expr *init, mlir::Location loc,
1042                       LValue lvalue, bool capturedByInit = false);
1043 
1044   void emitStaticVarDecl(const VarDecl &d, cir::GlobalLinkageKind linkage);
1045 
1046   void emitStoreOfComplex(mlir::Location loc, mlir::Value v, LValue dest,
1047                           bool isInit);
1048 
1049   void emitStoreOfScalar(mlir::Value value, Address addr, bool isVolatile,
1050                          clang::QualType ty, bool isInit = false,
1051                          bool isNontemporal = false);
1052   void emitStoreOfScalar(mlir::Value value, LValue lvalue, bool isInit);
1053 
1054   /// Store the specified rvalue into the specified
1055   /// lvalue, where both are guaranteed to the have the same type, and that type
1056   /// is 'Ty'.
1057   void emitStoreThroughLValue(RValue src, LValue dst, bool isInit = false);
1058 
1059   mlir::Value emitStoreThroughBitfieldLValue(RValue src, LValue dstresult);
1060 
1061   LValue emitStringLiteralLValue(const StringLiteral *e);
1062 
1063   mlir::LogicalResult emitSwitchBody(const clang::Stmt *s);
1064   mlir::LogicalResult emitSwitchCase(const clang::SwitchCase &s,
1065                                      bool buildingTopLevelCase);
1066   mlir::LogicalResult emitSwitchStmt(const clang::SwitchStmt &s);
1067 
1068   /// Given a value and its clang type, returns the value casted to its memory
1069   /// representation.
1070   /// Note: CIR defers most of the special casting to the final lowering passes
1071   /// to conserve the high level information.
1072   mlir::Value emitToMemory(mlir::Value value, clang::QualType ty);
1073 
1074   LValue emitUnaryOpLValue(const clang::UnaryOperator *e);
1075 
1076   /// This method handles emission of any variable declaration
1077   /// inside a function, including static vars etc.
1078   void emitVarDecl(const clang::VarDecl &d);
1079 
1080   mlir::LogicalResult emitWhileStmt(const clang::WhileStmt &s);
1081 
1082   /// Given an assignment `*lhs = rhs`, emit a test that checks if \p rhs is
1083   /// nonnull, if 1\p LHS is marked _Nonnull.
1084   void emitNullabilityCheck(LValue lhs, mlir::Value rhs,
1085                             clang::SourceLocation loc);
1086 
1087   /// An object to manage conditionally-evaluated expressions.
1088   class ConditionalEvaluation {
1089     CIRGenFunction &cgf;
1090     mlir::OpBuilder::InsertPoint insertPt;
1091 
1092   public:
ConditionalEvaluation(CIRGenFunction & cgf)1093     ConditionalEvaluation(CIRGenFunction &cgf)
1094         : cgf(cgf), insertPt(cgf.builder.saveInsertionPoint()) {}
ConditionalEvaluation(CIRGenFunction & cgf,mlir::OpBuilder::InsertPoint ip)1095     ConditionalEvaluation(CIRGenFunction &cgf, mlir::OpBuilder::InsertPoint ip)
1096         : cgf(cgf), insertPt(ip) {}
1097 
beginEvaluation()1098     void beginEvaluation() {
1099       assert(cgf.outermostConditional != this);
1100       if (!cgf.outermostConditional)
1101         cgf.outermostConditional = this;
1102     }
1103 
endEvaluation()1104     void endEvaluation() {
1105       assert(cgf.outermostConditional != nullptr);
1106       if (cgf.outermostConditional == this)
1107         cgf.outermostConditional = nullptr;
1108     }
1109 
1110     /// Returns the insertion point which will be executed prior to each
1111     /// evaluation of the conditional code. In LLVM OG, this method
1112     /// is called getStartingBlock.
getInsertPoint()1113     mlir::OpBuilder::InsertPoint getInsertPoint() const { return insertPt; }
1114   };
1115 
1116   struct ConditionalInfo {
1117     std::optional<LValue> lhs{}, rhs{};
1118     mlir::Value result{};
1119   };
1120 
1121   // Return true if we're currently emitting one branch or the other of a
1122   // conditional expression.
isInConditionalBranch()1123   bool isInConditionalBranch() const { return outermostConditional != nullptr; }
1124 
setBeforeOutermostConditional(mlir::Value value,Address addr)1125   void setBeforeOutermostConditional(mlir::Value value, Address addr) {
1126     assert(isInConditionalBranch());
1127     {
1128       mlir::OpBuilder::InsertionGuard guard(builder);
1129       builder.restoreInsertionPoint(outermostConditional->getInsertPoint());
1130       builder.createStore(
1131           value.getLoc(), value, addr,
1132           mlir::IntegerAttr::get(
1133               mlir::IntegerType::get(value.getContext(), 64),
1134               (uint64_t)addr.getAlignment().getAsAlign().value()));
1135     }
1136   }
1137 
1138   // Points to the outermost active conditional control. This is used so that
1139   // we know if a temporary should be destroyed conditionally.
1140   ConditionalEvaluation *outermostConditional = nullptr;
1141 
1142   template <typename FuncTy>
1143   ConditionalInfo emitConditionalBlocks(const AbstractConditionalOperator *e,
1144                                         const FuncTy &branchGenFunc);
1145 
1146   mlir::Value emitTernaryOnBoolExpr(const clang::Expr *cond, mlir::Location loc,
1147                                     const clang::Stmt *thenS,
1148                                     const clang::Stmt *elseS);
1149 
1150   /// ----------------------
1151   /// CIR build helpers
1152   /// -----------------
1153 public:
1154   cir::AllocaOp createTempAlloca(mlir::Type ty, mlir::Location loc,
1155                                  const Twine &name = "tmp",
1156                                  mlir::Value arraySize = nullptr,
1157                                  bool insertIntoFnEntryBlock = false);
1158   cir::AllocaOp createTempAlloca(mlir::Type ty, mlir::Location loc,
1159                                  const Twine &name = "tmp",
1160                                  mlir::OpBuilder::InsertPoint ip = {},
1161                                  mlir::Value arraySize = nullptr);
1162   Address createTempAlloca(mlir::Type ty, CharUnits align, mlir::Location loc,
1163                            const Twine &name = "tmp",
1164                            mlir::Value arraySize = nullptr,
1165                            Address *alloca = nullptr,
1166                            mlir::OpBuilder::InsertPoint ip = {});
1167   Address createTempAllocaWithoutCast(mlir::Type ty, CharUnits align,
1168                                       mlir::Location loc,
1169                                       const Twine &name = "tmp",
1170                                       mlir::Value arraySize = nullptr,
1171                                       mlir::OpBuilder::InsertPoint ip = {});
1172 
1173   /// Create a temporary memory object of the given type, with
1174   /// appropriate alignmen and cast it to the default address space. Returns
1175   /// the original alloca instruction by \p Alloca if it is not nullptr.
1176   Address createMemTemp(QualType t, mlir::Location loc,
1177                         const Twine &name = "tmp", Address *alloca = nullptr,
1178                         mlir::OpBuilder::InsertPoint ip = {});
1179   Address createMemTemp(QualType t, CharUnits align, mlir::Location loc,
1180                         const Twine &name = "tmp", Address *alloca = nullptr,
1181                         mlir::OpBuilder::InsertPoint ip = {});
1182 
1183   //===--------------------------------------------------------------------===//
1184   //                         OpenACC Emission
1185   //===--------------------------------------------------------------------===//
1186 private:
1187   template <typename Op>
1188   Op emitOpenACCOp(mlir::Location start, OpenACCDirectiveKind dirKind,
1189                    SourceLocation dirLoc,
1190                    llvm::ArrayRef<const OpenACCClause *> clauses);
1191   // Function to do the basic implementation of an operation with an Associated
1192   // Statement.  Models AssociatedStmtConstruct.
1193   template <typename Op, typename TermOp>
1194   mlir::LogicalResult emitOpenACCOpAssociatedStmt(
1195       mlir::Location start, mlir::Location end, OpenACCDirectiveKind dirKind,
1196       SourceLocation dirLoc, llvm::ArrayRef<const OpenACCClause *> clauses,
1197       const Stmt *associatedStmt);
1198 
1199   template <typename Op, typename TermOp>
1200   mlir::LogicalResult emitOpenACCOpCombinedConstruct(
1201       mlir::Location start, mlir::Location end, OpenACCDirectiveKind dirKind,
1202       SourceLocation dirLoc, llvm::ArrayRef<const OpenACCClause *> clauses,
1203       const Stmt *loopStmt);
1204 
1205   template <typename Op>
1206   void emitOpenACCClauses(Op &op, OpenACCDirectiveKind dirKind,
1207                           SourceLocation dirLoc,
1208                           ArrayRef<const OpenACCClause *> clauses);
1209   // The second template argument doesn't need to be a template, since it should
1210   // always be an mlir::acc::LoopOp, but as this is a template anyway, we make
1211   // it a template argument as this way we can avoid including the OpenACC MLIR
1212   // headers here. We will count on linker failures/explicit instantiation to
1213   // ensure we don't mess this up, but it is only called from 1 place, and
1214   // instantiated 3x.
1215   template <typename ComputeOp, typename LoopOp>
1216   void emitOpenACCClauses(ComputeOp &op, LoopOp &loopOp,
1217                           OpenACCDirectiveKind dirKind, SourceLocation dirLoc,
1218                           ArrayRef<const OpenACCClause *> clauses);
1219 
1220   // The OpenACC LoopOp requires that we have auto, seq, or independent on all
1221   // LoopOp operations for the 'none' device type case. This function checks if
1222   // the LoopOp has one, else it updates it to have one.
1223   void updateLoopOpParallelism(mlir::acc::LoopOp &op, bool isOrphan,
1224                                OpenACCDirectiveKind dk);
1225 
1226   // The OpenACC 'cache' construct actually applies to the 'loop' if present. So
1227   // keep track of the 'loop' so that we can add the cache vars to it correctly.
1228   mlir::acc::LoopOp *activeLoopOp = nullptr;
1229 
1230   struct ActiveOpenACCLoopRAII {
1231     CIRGenFunction &cgf;
1232     mlir::acc::LoopOp *oldLoopOp;
1233 
ActiveOpenACCLoopRAIIActiveOpenACCLoopRAII1234     ActiveOpenACCLoopRAII(CIRGenFunction &cgf, mlir::acc::LoopOp *newOp)
1235         : cgf(cgf), oldLoopOp(cgf.activeLoopOp) {
1236       cgf.activeLoopOp = newOp;
1237     }
~ActiveOpenACCLoopRAIIActiveOpenACCLoopRAII1238     ~ActiveOpenACCLoopRAII() { cgf.activeLoopOp = oldLoopOp; }
1239   };
1240 
1241 public:
1242   // Helper type used to store the list of important information for a 'data'
1243   // clause variable, or a 'cache' variable reference.
1244   struct OpenACCDataOperandInfo {
1245     mlir::Location beginLoc;
1246     mlir::Value varValue;
1247     std::string name;
1248     llvm::SmallVector<mlir::Value> bounds;
1249   };
1250   // Gets the collection of info required to lower and OpenACC clause or cache
1251   // construct variable reference.
1252   OpenACCDataOperandInfo getOpenACCDataOperandInfo(const Expr *e);
1253   // Helper function to emit the integer expressions as required by an OpenACC
1254   // clause/construct.
1255   mlir::Value emitOpenACCIntExpr(const Expr *intExpr);
1256   // Helper function to emit an integer constant as an mlir int type, used for
1257   // constants in OpenACC constructs/clauses.
1258   mlir::Value createOpenACCConstantInt(mlir::Location loc, unsigned width,
1259                                        int64_t value);
1260 
1261   mlir::LogicalResult
1262   emitOpenACCComputeConstruct(const OpenACCComputeConstruct &s);
1263   mlir::LogicalResult emitOpenACCLoopConstruct(const OpenACCLoopConstruct &s);
1264   mlir::LogicalResult
1265   emitOpenACCCombinedConstruct(const OpenACCCombinedConstruct &s);
1266   mlir::LogicalResult emitOpenACCDataConstruct(const OpenACCDataConstruct &s);
1267   mlir::LogicalResult
1268   emitOpenACCEnterDataConstruct(const OpenACCEnterDataConstruct &s);
1269   mlir::LogicalResult
1270   emitOpenACCExitDataConstruct(const OpenACCExitDataConstruct &s);
1271   mlir::LogicalResult
1272   emitOpenACCHostDataConstruct(const OpenACCHostDataConstruct &s);
1273   mlir::LogicalResult emitOpenACCWaitConstruct(const OpenACCWaitConstruct &s);
1274   mlir::LogicalResult emitOpenACCInitConstruct(const OpenACCInitConstruct &s);
1275   mlir::LogicalResult
1276   emitOpenACCShutdownConstruct(const OpenACCShutdownConstruct &s);
1277   mlir::LogicalResult emitOpenACCSetConstruct(const OpenACCSetConstruct &s);
1278   mlir::LogicalResult
1279   emitOpenACCUpdateConstruct(const OpenACCUpdateConstruct &s);
1280   mlir::LogicalResult
1281   emitOpenACCAtomicConstruct(const OpenACCAtomicConstruct &s);
1282   mlir::LogicalResult emitOpenACCCacheConstruct(const OpenACCCacheConstruct &s);
1283 
1284   void emitOpenACCDeclare(const OpenACCDeclareDecl &d);
1285   void emitOpenACCRoutine(const OpenACCRoutineDecl &d);
1286 
1287   /// Create a temporary memory object for the given aggregate type.
1288   AggValueSlot createAggTemp(QualType ty, mlir::Location loc,
1289                              const Twine &name = "tmp",
1290                              Address *alloca = nullptr) {
1291     assert(!cir::MissingFeatures::aggValueSlot());
1292     return AggValueSlot::forAddr(
1293         createMemTemp(ty, loc, name, alloca), ty.getQualifiers(),
1294         AggValueSlot::IsNotDestructed, AggValueSlot::IsNotAliased,
1295         AggValueSlot::DoesNotOverlap);
1296   }
1297 
1298 private:
1299   QualType getVarArgType(const Expr *arg);
1300 };
1301 
1302 } // namespace clang::CIRGen
1303 
1304 #endif
1305