Thanks to visit codestin.com
Credit goes to clang.llvm.org

clang 22.0.0git
CIRGenFunction.h
Go to the documentation of this file.
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#include "EHScopeStack.h"
22
23#include "Address.h"
24
27#include "clang/AST/CharUnits.h"
29#include "clang/AST/Decl.h"
30#include "clang/AST/ExprCXX.h"
31#include "clang/AST/Stmt.h"
32#include "clang/AST/Type.h"
36#include "llvm/ADT/ScopedHashTable.h"
37
38namespace {
39class ScalarExprEmitter;
40} // namespace
41
42namespace mlir {
43namespace acc {
44class LoopOp;
45} // namespace acc
46} // namespace mlir
47
48namespace clang::CIRGen {
49
51public:
53
54private:
55 friend class ::ScalarExprEmitter;
56 /// The builder is a helper class to create IR inside a function. The
57 /// builder is stateful, in particular it keeps an "insertion point": this
58 /// is where the next operations will be introduced.
59 CIRGenBuilderTy &builder;
60
61public:
62 /// The GlobalDecl for the current function being compiled or the global
63 /// variable currently being initialized.
65
66 /// The compiler-generated variable that holds the return value.
67 std::optional<mlir::Value> fnRetAlloca;
68
69 /// The temporary alloca to hold the return value. This is
70 /// invalid iff the function has no return value.
72
73 /// Tracks function scope overall cleanup handling.
75
76 llvm::DenseMap<const clang::ValueDecl *, clang::FieldDecl *>
79
80 /// CXXThisDecl - When generating code for a C++ member function,
81 /// this will hold the implicit 'this' declaration.
83 mlir::Value cxxabiThisValue = nullptr;
84 mlir::Value cxxThisValue = nullptr;
86
87 /// When generating code for a constructor or destructor, this will hold the
88 /// implicit argument (e.g. VTT).
91
92 /// The value of 'this' to sue when evaluating CXXDefaultInitExprs within this
93 /// expression.
95
96 // Holds the Decl for the current outermost non-closure context
97 const clang::Decl *curFuncDecl = nullptr;
98 /// This is the inner-most code context, which includes blocks.
99 const clang::Decl *curCodeDecl = nullptr;
100
101 /// The current function or global initializer that is generated code for.
102 /// This is usually a cir::FuncOp, but it can also be a cir::GlobalOp for
103 /// global initializers.
104 mlir::Operation *curFn = nullptr;
105
106 using DeclMapTy = llvm::DenseMap<const clang::Decl *, Address>;
107 /// This keeps track of the CIR allocas or globals for local C
108 /// declarations.
110
111 /// The type of the condition for the emitting switch statement.
113
114 clang::ASTContext &getContext() const { return cgm.getASTContext(); }
115
116 CIRGenBuilderTy &getBuilder() { return builder; }
117
119 const CIRGenModule &getCIRGenModule() const { return cgm; }
120
122 // We currently assume this isn't called for a global initializer.
123 auto fn = mlir::cast<cir::FuncOp>(curFn);
124 return &fn.getRegion().front();
125 }
126
127 /// Sanitizers enabled for this function.
129
130 /// The symbol table maps a variable name to a value in the current scope.
131 /// Entering a function creates a new scope, and the function arguments are
132 /// added to the mapping. When the processing of a function is terminated,
133 /// the scope is destroyed and the mappings created in this scope are
134 /// dropped.
135 using SymTableTy = llvm::ScopedHashTable<const clang::Decl *, mlir::Value>;
137
138 /// Whether or not a Microsoft-style asm block has been processed within
139 /// this fuction. These can potentially set the return value.
140 bool sawAsmBlock = false;
141
142 mlir::Type convertTypeForMem(QualType t);
143
144 mlir::Type convertType(clang::QualType t);
145 mlir::Type convertType(const TypeDecl *t) {
146 return convertType(getContext().getTypeDeclType(t));
147 }
148
149 /// Return the cir::TypeEvaluationKind of QualType \c type.
151
155
159
161 bool suppressNewContext = false);
163
164 CIRGenTypes &getTypes() const { return cgm.getTypes(); }
165
166 const TargetInfo &getTarget() const { return cgm.getTarget(); }
167 mlir::MLIRContext &getMLIRContext() { return cgm.getMLIRContext(); }
168
169 // ---------------------
170 // Opaque value handling
171 // ---------------------
172
173 /// Keeps track of the current set of opaque value expressions.
174 llvm::DenseMap<const OpaqueValueExpr *, LValue> opaqueLValues;
175 llvm::DenseMap<const OpaqueValueExpr *, RValue> opaqueRValues;
176
177public:
178 /// A non-RAII class containing all the information about a bound
179 /// opaque value. OpaqueValueMapping, below, is a RAII wrapper for
180 /// this which makes individual mappings very simple; using this
181 /// class directly is useful when you have a variable number of
182 /// opaque values or don't want the RAII functionality for some
183 /// reason.
184 class OpaqueValueMappingData {
185 const OpaqueValueExpr *opaqueValue;
186 bool boundLValue;
187
188 OpaqueValueMappingData(const OpaqueValueExpr *ov, bool boundLValue)
189 : opaqueValue(ov), boundLValue(boundLValue) {}
190
191 public:
192 OpaqueValueMappingData() : opaqueValue(nullptr) {}
193
194 static bool shouldBindAsLValue(const Expr *expr) {
195 // gl-values should be bound as l-values for obvious reasons.
196 // Records should be bound as l-values because IR generation
197 // always keeps them in memory. Expressions of function type
198 // act exactly like l-values but are formally required to be
199 // r-values in C.
200 return expr->isGLValue() || expr->getType()->isFunctionType() ||
202 }
203
205 bind(CIRGenFunction &cgf, const OpaqueValueExpr *ov, const Expr *e) {
206 if (shouldBindAsLValue(ov))
207 return bind(cgf, ov, cgf.emitLValue(e));
208 return bind(cgf, ov, cgf.emitAnyExpr(e));
209 }
210
212 bind(CIRGenFunction &cgf, const OpaqueValueExpr *ov, const LValue &lv) {
213 assert(shouldBindAsLValue(ov));
214 cgf.opaqueLValues.insert(std::make_pair(ov, lv));
215 return OpaqueValueMappingData(ov, true);
216 }
217
219 bind(CIRGenFunction &cgf, const OpaqueValueExpr *ov, const RValue &rv) {
220 assert(!shouldBindAsLValue(ov));
221 cgf.opaqueRValues.insert(std::make_pair(ov, rv));
222
223 OpaqueValueMappingData data(ov, false);
224
225 // Work around an extremely aggressive peephole optimization in
226 // EmitScalarConversion which assumes that all other uses of a
227 // value are extant.
229 return data;
230 }
231
232 bool isValid() const { return opaqueValue != nullptr; }
233 void clear() { opaqueValue = nullptr; }
234
236 assert(opaqueValue && "no data to unbind!");
237
238 if (boundLValue) {
239 cgf.opaqueLValues.erase(opaqueValue);
240 } else {
241 cgf.opaqueRValues.erase(opaqueValue);
243 }
244 }
245 };
246
247 /// An RAII object to set (and then clear) a mapping for an OpaqueValueExpr.
249 CIRGenFunction &cgf;
251
252 public:
256
257 /// Build the opaque value mapping for the given conditional
258 /// operator if it's the GNU ?: extension. This is a common
259 /// enough pattern that the convenience operator is really
260 /// helpful.
261 ///
264 : cgf(cgf) {
265 if (mlir::isa<ConditionalOperator>(op))
266 // Leave Data empty.
267 return;
268
270 mlir::cast<BinaryConditionalOperator>(op);
272 e->getCommon());
273 }
274
275 /// Build the opaque value mapping for an OpaqueValueExpr whose source
276 /// expression is set to the expression the OVE represents.
278 : cgf(cgf) {
279 if (ov) {
280 assert(ov->getSourceExpr() && "wrong form of OpaqueValueMapping used "
281 "for OVE with no source expression");
282 data = OpaqueValueMappingData::bind(cgf, ov, ov->getSourceExpr());
283 }
284 }
285
287 LValue lvalue)
288 : cgf(cgf),
289 data(OpaqueValueMappingData::bind(cgf, opaqueValue, lvalue)) {}
290
292 RValue rvalue)
293 : cgf(cgf),
294 data(OpaqueValueMappingData::bind(cgf, opaqueValue, rvalue)) {}
295
296 void pop() {
297 data.unbind(cgf);
298 data.clear();
299 }
300
302 if (data.isValid())
303 data.unbind(cgf);
304 }
305 };
306
307private:
308 /// Declare a variable in the current scope, return success if the variable
309 /// wasn't declared yet.
310 void declare(mlir::Value addrVal, const clang::Decl *var, clang::QualType ty,
311 mlir::Location loc, clang::CharUnits alignment,
312 bool isParam = false);
313
314public:
315 mlir::Value createDummyValue(mlir::Location loc, clang::QualType qt);
316
317 void emitNullInitialization(mlir::Location loc, Address destPtr, QualType ty);
318
319private:
320 // Track current variable initialization (if there's one)
321 const clang::VarDecl *currVarDecl = nullptr;
322 class VarDeclContext {
324 const clang::VarDecl *oldVal = nullptr;
325
326 public:
327 VarDeclContext(CIRGenFunction &p, const VarDecl *value) : p(p) {
328 if (p.currVarDecl)
329 oldVal = p.currVarDecl;
330 p.currVarDecl = value;
331 }
332
333 /// Can be used to restore the state early, before the dtor
334 /// is run.
335 void restore() { p.currVarDecl = oldVal; }
336 ~VarDeclContext() { restore(); }
337 };
338
339public:
340 /// Use to track source locations across nested visitor traversals.
341 /// Always use a `SourceLocRAIIObject` to change currSrcLoc.
342 std::optional<mlir::Location> currSrcLoc;
344 CIRGenFunction &cgf;
345 std::optional<mlir::Location> oldLoc;
346
347 public:
348 SourceLocRAIIObject(CIRGenFunction &cgf, mlir::Location value) : cgf(cgf) {
349 if (cgf.currSrcLoc)
350 oldLoc = cgf.currSrcLoc;
351 cgf.currSrcLoc = value;
352 }
353
354 /// Can be used to restore the state early, before the dtor
355 /// is run.
356 void restore() { cgf.currSrcLoc = oldLoc; }
358 };
359
361 llvm::ScopedHashTableScope<const clang::Decl *, mlir::Value>;
362
363 /// Hold counters for incrementally naming temporaries
364 unsigned counterRefTmp = 0;
365 unsigned counterAggTmp = 0;
366 std::string getCounterRefTmpAsString();
367 std::string getCounterAggTmpAsString();
368
369 /// Helpers to convert Clang's SourceLocation to a MLIR Location.
370 mlir::Location getLoc(clang::SourceLocation srcLoc);
371 mlir::Location getLoc(clang::SourceRange srcLoc);
372 mlir::Location getLoc(mlir::Location lhs, mlir::Location rhs);
373
374 const clang::LangOptions &getLangOpts() const { return cgm.getLangOpts(); }
375
376 /// True if an insertion point is defined. If not, this indicates that the
377 /// current code being emitted is unreachable.
378 /// FIXME(cir): we need to inspect this and perhaps use a cleaner mechanism
379 /// since we don't yet force null insertion point to designate behavior (like
380 /// LLVM's codegen does) and we probably shouldn't.
381 bool haveInsertPoint() const {
382 return builder.getInsertionBlock() != nullptr;
383 }
384
385 // Wrapper for function prototype sources. Wraps either a FunctionProtoType or
386 // an ObjCMethodDecl.
388 llvm::PointerUnion<const clang::FunctionProtoType *,
389 const clang::ObjCMethodDecl *>
391
394 };
395
397
398 /// An abstract representation of regular/ObjC call/message targets.
400 /// The function declaration of the callee.
401 [[maybe_unused]] const clang::Decl *calleeDecl;
402
403 public:
404 AbstractCallee() : calleeDecl(nullptr) {}
405 AbstractCallee(const clang::FunctionDecl *fd) : calleeDecl(fd) {}
406
407 bool hasFunctionDecl() const {
408 return llvm::isa_and_nonnull<clang::FunctionDecl>(calleeDecl);
409 }
410
411 unsigned getNumParams() const {
412 if (const auto *fd = llvm::dyn_cast<clang::FunctionDecl>(calleeDecl))
413 return fd->getNumParams();
414 return llvm::cast<clang::ObjCMethodDecl>(calleeDecl)->param_size();
415 }
416
417 const clang::ParmVarDecl *getParamDecl(unsigned I) const {
418 if (const auto *fd = llvm::dyn_cast<clang::FunctionDecl>(calleeDecl))
419 return fd->getParamDecl(I);
420 return *(llvm::cast<clang::ObjCMethodDecl>(calleeDecl)->param_begin() +
421 I);
422 }
423 };
424
425 void finishFunction(SourceLocation endLoc);
426
427 /// Determine whether the given initializer is trivial in the sense
428 /// that it requires no code to be generated.
429 bool isTrivialInitializer(const Expr *init);
430
431 /// If the specified expression does not fold to a constant, or if it does but
432 /// contains a label, return false. If it constant folds return true and set
433 /// the boolean result in Result.
434 bool constantFoldsToBool(const clang::Expr *cond, bool &resultBool,
435 bool allowLabels = false);
437 llvm::APSInt &resultInt,
438 bool allowLabels = false);
439
440 /// Return true if the statement contains a label in it. If
441 /// this statement is not executed normally, it not containing a label means
442 /// that we can just remove the code.
443 bool containsLabel(const clang::Stmt *s, bool ignoreCaseStmts = false);
444
445 class ConstantEmission {
446 // Cannot use mlir::TypedAttr directly here because of bit availability.
447 llvm::PointerIntPair<mlir::Attribute, 1, bool> valueAndIsReference;
448 ConstantEmission(mlir::TypedAttr c, bool isReference)
449 : valueAndIsReference(c, isReference) {}
450
451 public:
453 static ConstantEmission forReference(mlir::TypedAttr c) {
454 return ConstantEmission(c, true);
455 }
456 static ConstantEmission forValue(mlir::TypedAttr c) {
457 return ConstantEmission(c, false);
458 }
459
460 explicit operator bool() const {
461 return valueAndIsReference.getOpaqueValue() != nullptr;
462 }
463
464 bool isReference() const { return valueAndIsReference.getInt(); }
466 assert(isReference());
467 cgf.cgm.errorNYI(refExpr->getSourceRange(),
468 "ConstantEmission::getReferenceLValue");
469 return {};
470 }
471
472 mlir::TypedAttr getValue() const {
473 assert(!isReference());
474 return mlir::cast<mlir::TypedAttr>(valueAndIsReference.getPointer());
475 }
476 };
477
478 ConstantEmission tryEmitAsConstant(const DeclRefExpr *refExpr);
479 ConstantEmission tryEmitAsConstant(const MemberExpr *me);
480
483 /// The address of the alloca for languages with explicit address space
484 /// (e.g. OpenCL) or alloca casted to generic pointer for address space
485 /// agnostic languages (e.g. C++). Invalid if the variable was emitted
486 /// as a global constant.
488
489 /// True if the variable is of aggregate type and has a constant
490 /// initializer.
492
493 /// True if the variable is a __block variable that is captured by an
494 /// escaping block.
495 bool IsEscapingByRef = false;
496
497 /// True if the variable was emitted as an offload recipe, and thus doesn't
498 /// have the same sort of alloca initialization.
499 bool EmittedAsOffload = false;
500
501 mlir::Value NRVOFlag{};
502
503 struct Invalid {};
505
507 : Variable(&variable), Addr(Address::invalid()) {}
508
510
511 bool wasEmittedAsGlobal() const { return !Addr.isValid(); }
512
514
515 /// Returns the raw, allocated address, which is not necessarily
516 /// the address of the object itself. It is casted to default
517 /// address space for address space agnostic languages.
518 Address getAllocatedAddress() const { return Addr; }
519
520 // Changes the stored address for the emission. This function should only
521 // be used in extreme cases, and isn't required to model normal AST
522 // initialization/variables.
524
525 /// Returns the address of the object within this declaration.
526 /// Note that this does not chase the forwarding pointer for
527 /// __block decls.
529 if (!IsEscapingByRef)
530 return Addr;
531
533 return Address::invalid();
534 }
535 };
536
537 /// Perform the usual unary conversions on the specified expression and
538 /// compare the result against zero, returning an Int1Ty value.
539 mlir::Value evaluateExprAsBool(const clang::Expr *e);
540
541 cir::GlobalOp addInitializerToStaticVarDecl(const VarDecl &d,
542 cir::GlobalOp gv,
543 cir::GetGlobalOp gvAddr);
544
545 /// Set the address of a local variable.
547 assert(!localDeclMap.count(vd) && "Decl already exists in LocalDeclMap!");
548 localDeclMap.insert({vd, addr});
549
550 // Add to the symbol table if not there already.
551 if (symbolTable.count(vd))
552 return;
553 symbolTable.insert(vd, addr.getPointer());
554 }
555
556 // A class to allow reverting changes to a var-decl's registration to the
557 // localDeclMap. This is used in cases where things are being inserted into
558 // the variable list but don't follow normal lookup/search rules, like in
559 // OpenACC recipe generation.
561 CIRGenFunction &cgf;
562 const VarDecl *vd;
563 bool shouldDelete = false;
564 Address oldAddr = Address::invalid();
565
566 public:
568 : cgf(cgf), vd(vd) {
569 auto mapItr = cgf.localDeclMap.find(vd);
570
571 if (mapItr != cgf.localDeclMap.end())
572 oldAddr = mapItr->second;
573 else
574 shouldDelete = true;
575 }
576
578 if (shouldDelete)
579 cgf.localDeclMap.erase(vd);
580 else
581 cgf.localDeclMap.insert_or_assign(vd, oldAddr);
582 }
583 };
584
586
589
590 static bool
592
599
602
606 const clang::CXXRecordDecl *nearestVBase,
607 clang::CharUnits offsetFromNearestVBase,
608 bool baseIsNonVirtualPrimaryBase,
609 const clang::CXXRecordDecl *vtableClass,
610 VisitedVirtualBasesSetTy &vbases, VPtrsVector &vptrs);
611 /// Return the Value of the vtable pointer member pointed to by thisAddr.
612 mlir::Value getVTablePtr(mlir::Location loc, Address thisAddr,
613 const clang::CXXRecordDecl *vtableClass);
614
615 /// Returns whether we should perform a type checked load when loading a
616 /// virtual function for virtual calls to members of RD. This is generally
617 /// true when both vcall CFI and whole-program-vtables are enabled.
619
620 /// Source location information about the default argument or member
621 /// initializer expression we're evaluating, if any.
625
626 /// A scope within which we are constructing the fields of an object which
627 /// might use a CXXDefaultInitExpr. This stashes away a 'this' value to use if
628 /// we need to evaluate the CXXDefaultInitExpr within the evaluation.
630 public:
632 : cgf(cgf), oldCXXDefaultInitExprThis(cgf.cxxDefaultInitExprThis) {
633 cgf.cxxDefaultInitExprThis = thisAddr;
634 }
636 cgf.cxxDefaultInitExprThis = oldCXXDefaultInitExprThis;
637 }
638
639 private:
640 CIRGenFunction &cgf;
641 Address oldCXXDefaultInitExprThis;
642 };
643
644 /// The scope of a CXXDefaultInitExpr. Within this scope, the value of 'this'
645 /// is overridden to be the object under construction.
647 public:
652 cgf.cxxThisValue = cgf.cxxDefaultInitExprThis.getPointer();
653 cgf.cxxThisAlignment = cgf.cxxDefaultInitExprThis.getAlignment();
654 }
656 cgf.cxxThisValue = oldCXXThisValue;
657 cgf.cxxThisAlignment = oldCXXThisAlignment;
658 }
659
660 public:
662 mlir::Value oldCXXThisValue;
665 };
666
668 LValue makeNaturalAlignAddrLValue(mlir::Value val, QualType ty);
669
670 /// Construct an address with the natural alignment of T. If a pointer to T
671 /// is expected to be signed, the pointer passed to this function must have
672 /// been signed, and the returned Address will have the pointer authentication
673 /// information needed to authenticate the signed pointer.
675 CharUnits alignment,
676 bool forPointeeType = false,
677 LValueBaseInfo *baseInfo = nullptr) {
678 if (alignment.isZero())
679 alignment = cgm.getNaturalTypeAlignment(t, baseInfo);
680 return Address(ptr, convertTypeForMem(t), alignment);
681 }
682
684 Address value, const CXXRecordDecl *derived,
685 llvm::iterator_range<CastExpr::path_const_iterator> path,
686 bool nullCheckValue, SourceLocation loc);
687
688 /// Return the VTT parameter that should be passed to a base
689 /// constructor/destructor with virtual bases.
690 /// FIXME: VTTs are Itanium ABI-specific, so the definition should move
691 /// to ItaniumCXXABI.cpp together with all the references to VTT.
692 mlir::Value getVTTParameter(GlobalDecl gd, bool forVirtualBase,
693 bool delegating);
694
697 return makeAddrLValue(addr, ty, LValueBaseInfo(source));
698 }
699
701 return LValue::makeAddr(addr, ty, baseInfo);
702 }
703
704 void initializeVTablePointers(mlir::Location loc,
705 const clang::CXXRecordDecl *rd);
706 void initializeVTablePointer(mlir::Location loc, const VPtr &vptr);
707
709
710 /// Return the address of a local variable.
712 auto it = localDeclMap.find(vd);
713 assert(it != localDeclMap.end() &&
714 "Invalid argument to getAddrOfLocalVar(), no decl!");
715 return it->second;
716 }
717
719 mlir::Type fieldType, unsigned index);
720
721 /// Given an opaque value expression, return its LValue mapping if it exists,
722 /// otherwise create one.
724
725 /// Given an opaque value expression, return its RValue mapping if it exists,
726 /// otherwise create one.
728
729 /// Load the value for 'this'. This function is only valid while generating
730 /// code for an C++ member function.
731 /// FIXME(cir): this should return a mlir::Value!
732 mlir::Value loadCXXThis() {
733 assert(cxxThisValue && "no 'this' value for this function");
734 return cxxThisValue;
735 }
737
738 /// Load the VTT parameter to base constructors/destructors have virtual
739 /// bases. FIXME: Every place that calls LoadCXXVTT is something that needs to
740 /// be abstracted properly.
741 mlir::Value loadCXXVTT() {
742 assert(cxxStructorImplicitParamValue && "no VTT value for this function");
744 }
745
746 /// Convert the given pointer to a complete class to the given direct base.
748 Address value,
749 const CXXRecordDecl *derived,
750 const CXXRecordDecl *base,
751 bool baseIsVirtual);
752
753 /// Determine whether a return value slot may overlap some other object.
755 // FIXME: Assuming no overlap here breaks guaranteed copy elision for base
756 // class subobjects. These cases may need to be revisited depending on the
757 // resolution of the relevant core issue.
759 }
760
761 /// Determine whether a base class initialization may overlap some other
762 /// object.
764 const CXXRecordDecl *baseRD,
765 bool isVirtual);
766
767 /// Get an appropriate 'undef' rvalue for the given type.
768 /// TODO: What's the equivalent for MLIR? Currently we're only using this for
769 /// void types so it just returns RValue::get(nullptr) but it'll need
770 /// addressed later.
772
773 cir::FuncOp generateCode(clang::GlobalDecl gd, cir::FuncOp fn,
774 cir::FuncType funcType);
775
777 FunctionArgList &args);
778
779 /// Emit code for the start of a function.
780 /// \param loc The location to be associated with the function.
781 /// \param startLoc The location of the function body.
783 cir::FuncOp fn, cir::FuncType funcType,
785 clang::SourceLocation startLoc);
786
787 /// The cleanup depth enclosing all the cleanups associated with the
788 /// parameters.
790
791 /// Takes the old cleanup stack size and emits the cleanup blocks
792 /// that have been added.
793 void popCleanupBlocks(EHScopeStack::stable_iterator oldCleanupStackDepth);
794 void popCleanupBlock();
795
796 /// Push a cleanup to be run at the end of the current full-expression. Safe
797 /// against the possibility that we're currently inside a
798 /// conditionally-evaluated expression.
799 template <class T, class... As>
800 void pushFullExprCleanup(CleanupKind kind, As... a) {
801 // If we're not in a conditional branch, or if none of the
802 // arguments requires saving, then use the unconditional cleanup.
804 return ehStack.pushCleanup<T>(kind, a...);
805
806 cgm.errorNYI("pushFullExprCleanup in conditional branch");
807 }
808
809 /// Enters a new scope for capturing cleanups, all of which
810 /// will be executed once the scope is exited.
811 class RunCleanupsScope {
812 EHScopeStack::stable_iterator cleanupStackDepth, oldCleanupStackDepth;
813
814 protected:
816
817 private:
818 RunCleanupsScope(const RunCleanupsScope &) = delete;
819 void operator=(const RunCleanupsScope &) = delete;
820
821 protected:
823
824 public:
825 /// Enter a new cleanup scope.
828 cleanupStackDepth = cgf.ehStack.stable_begin();
829 oldCleanupStackDepth = cgf.currentCleanupStackDepth;
830 cgf.currentCleanupStackDepth = cleanupStackDepth;
831 }
832
833 /// Exit this cleanup scope, emitting any accumulated cleanups.
838
839 /// Force the emission of cleanups now, instead of waiting
840 /// until this object is destroyed.
842 assert(performCleanup && "Already forced cleanup");
843 {
844 mlir::OpBuilder::InsertionGuard guard(cgf.getBuilder());
845 cgf.popCleanupBlocks(cleanupStackDepth);
846 performCleanup = false;
847 cgf.currentCleanupStackDepth = oldCleanupStackDepth;
848 }
849 }
850 };
851
852 // Cleanup stack depth of the RunCleanupsScope that was pushed most recently.
854
855public:
856 /// Represents a scope, including function bodies, compound statements, and
857 /// the substatements of if/while/do/for/switch/try statements. This class
858 /// handles any automatic cleanup, along with the return value.
859 struct LexicalScope : public RunCleanupsScope {
860 private:
861 // Block containing cleanup code for things initialized in this
862 // lexical context (scope).
863 mlir::Block *cleanupBlock = nullptr;
864
865 // Points to the scope entry block. This is useful, for instance, for
866 // helping to insert allocas before finalizing any recursive CodeGen from
867 // switches.
868 mlir::Block *entryBlock;
869
870 LexicalScope *parentScope = nullptr;
871
872 // Only Regular is used at the moment. Support for other kinds will be
873 // added as the relevant statements/expressions are upstreamed.
874 enum Kind {
875 Regular, // cir.if, cir.scope, if_regions
876 Ternary, // cir.ternary
877 Switch, // cir.switch
878 Try, // cir.try
879 GlobalInit // cir.global initialization code
880 };
881 Kind scopeKind = Kind::Regular;
882
883 // The scope return value.
884 mlir::Value retVal = nullptr;
885
886 mlir::Location beginLoc;
887 mlir::Location endLoc;
888
889 public:
890 unsigned depth = 0;
891
892 LexicalScope(CIRGenFunction &cgf, mlir::Location loc, mlir::Block *eb)
893 : RunCleanupsScope(cgf), entryBlock(eb), parentScope(cgf.curLexScope),
894 beginLoc(loc), endLoc(loc) {
895
896 assert(entryBlock && "LexicalScope requires an entry block");
897 cgf.curLexScope = this;
898 if (parentScope)
899 ++depth;
900
901 if (const auto fusedLoc = mlir::dyn_cast<mlir::FusedLoc>(loc)) {
902 assert(fusedLoc.getLocations().size() == 2 && "too many locations");
903 beginLoc = fusedLoc.getLocations()[0];
904 endLoc = fusedLoc.getLocations()[1];
905 }
906 }
907
908 void setRetVal(mlir::Value v) { retVal = v; }
909
910 void cleanup();
911 void restore() { cgf.curLexScope = parentScope; }
912
918
919 // ---
920 // Kind
921 // ---
922 bool isGlobalInit() { return scopeKind == Kind::GlobalInit; }
923 bool isRegular() { return scopeKind == Kind::Regular; }
924 bool isSwitch() { return scopeKind == Kind::Switch; }
925 bool isTernary() { return scopeKind == Kind::Ternary; }
926 bool isTry() { return scopeKind == Kind::Try; }
927
928 void setAsGlobalInit() { scopeKind = Kind::GlobalInit; }
929 void setAsSwitch() { scopeKind = Kind::Switch; }
930 void setAsTernary() { scopeKind = Kind::Ternary; }
931
932 // Lazy create cleanup block or return what's available.
933 mlir::Block *getOrCreateCleanupBlock(mlir::OpBuilder &builder) {
934 if (cleanupBlock)
935 return cleanupBlock;
936 cleanupBlock = createCleanupBlock(builder);
937 return cleanupBlock;
938 }
939
940 mlir::Block *getCleanupBlock(mlir::OpBuilder &builder) {
941 return cleanupBlock;
942 }
943
944 mlir::Block *createCleanupBlock(mlir::OpBuilder &builder) {
945 // Create the cleanup block but dont hook it up around just yet.
946 mlir::OpBuilder::InsertionGuard guard(builder);
947 mlir::Region *r = builder.getBlock() ? builder.getBlock()->getParent()
948 : &cgf.curFn->getRegion(0);
949 cleanupBlock = builder.createBlock(r);
950 return cleanupBlock;
951 }
952
953 // ---
954 // Return handling.
955 // ---
956
957 private:
958 // `returnBlock`, `returnLoc`, and all the functions that deal with them
959 // will change and become more complicated when `switch` statements are
960 // upstreamed. `case` statements within the `switch` are in the same scope
961 // but have their own regions. Therefore the LexicalScope will need to
962 // keep track of multiple return blocks.
963 mlir::Block *returnBlock = nullptr;
964 std::optional<mlir::Location> returnLoc;
965
966 // See the comment on `getOrCreateRetBlock`.
967 mlir::Block *createRetBlock(CIRGenFunction &cgf, mlir::Location loc) {
968 assert(returnBlock == nullptr && "only one return block per scope");
969 // Create the cleanup block but don't hook it up just yet.
970 mlir::OpBuilder::InsertionGuard guard(cgf.builder);
971 returnBlock =
972 cgf.builder.createBlock(cgf.builder.getBlock()->getParent());
973 updateRetLoc(returnBlock, loc);
974 return returnBlock;
975 }
976
977 cir::ReturnOp emitReturn(mlir::Location loc);
978 void emitImplicitReturn();
979
980 public:
981 mlir::Block *getRetBlock() { return returnBlock; }
982 mlir::Location getRetLoc(mlir::Block *b) { return *returnLoc; }
983 void updateRetLoc(mlir::Block *b, mlir::Location loc) { returnLoc = loc; }
984
985 // Create the return block for this scope, or return the existing one.
986 // This get-or-create logic is necessary to handle multiple return
987 // statements within the same scope, which can happen if some of them are
988 // dead code or if there is a `goto` into the middle of the scope.
989 mlir::Block *getOrCreateRetBlock(CIRGenFunction &cgf, mlir::Location loc) {
990 if (returnBlock == nullptr) {
991 returnBlock = createRetBlock(cgf, loc);
992 return returnBlock;
993 }
994 updateRetLoc(returnBlock, loc);
995 return returnBlock;
996 }
997
998 mlir::Block *getEntryBlock() { return entryBlock; }
999 };
1000
1002
1003 typedef void Destroyer(CIRGenFunction &cgf, Address addr, QualType ty);
1004
1006
1007 void pushDestroy(CleanupKind kind, Address addr, QualType type,
1008 Destroyer *destroyer);
1009
1011
1012 /// ----------------------
1013 /// CIR emit functions
1014 /// ----------------------
1015public:
1016 mlir::Value emitAlignmentAssumption(mlir::Value ptrValue, QualType ty,
1017 SourceLocation loc,
1018 SourceLocation assumptionLoc,
1019 int64_t alignment,
1020 mlir::Value offsetValue = nullptr);
1021
1022 mlir::Value emitAlignmentAssumption(mlir::Value ptrValue, const Expr *expr,
1023 SourceLocation assumptionLoc,
1024 int64_t alignment,
1025 mlir::Value offsetValue = nullptr);
1026
1027private:
1028 void emitAndUpdateRetAlloca(clang::QualType type, mlir::Location loc,
1029 clang::CharUnits alignment);
1030
1031 CIRGenCallee emitDirectCallee(const GlobalDecl &gd);
1032
1033public:
1035 llvm::StringRef fieldName,
1036 unsigned fieldIndex);
1037
1038 mlir::Value emitAlloca(llvm::StringRef name, mlir::Type ty,
1039 mlir::Location loc, clang::CharUnits alignment,
1040 bool insertIntoFnEntryBlock,
1041 mlir::Value arraySize = nullptr);
1042 mlir::Value emitAlloca(llvm::StringRef name, mlir::Type ty,
1043 mlir::Location loc, clang::CharUnits alignment,
1044 mlir::OpBuilder::InsertPoint ip,
1045 mlir::Value arraySize = nullptr);
1046
1047 void emitAggregateStore(mlir::Value value, Address dest);
1048
1049 void emitAggExpr(const clang::Expr *e, AggValueSlot slot);
1050
1052
1053 /// Emit an aggregate copy.
1054 ///
1055 /// \param isVolatile \c true iff either the source or the destination is
1056 /// volatile.
1057 /// \param MayOverlap Whether the tail padding of the destination might be
1058 /// occupied by some other object. More efficient code can often be
1059 /// generated if not.
1060 void emitAggregateCopy(LValue dest, LValue src, QualType eltTy,
1061 AggValueSlot::Overlap_t mayOverlap);
1062
1063 /// Emit code to compute the specified expression which can have any type. The
1064 /// result is returned as an RValue struct. If this is an aggregate
1065 /// expression, the aggloc/agglocvolatile arguments indicate where the result
1066 /// should be returned.
1069
1070 /// Emits the code necessary to evaluate an arbitrary expression into the
1071 /// given memory location.
1072 void emitAnyExprToMem(const Expr *e, Address location, Qualifiers quals,
1073 bool isInitializer);
1074
1075 /// Similarly to emitAnyExpr(), however, the result will always be accessible
1076 /// even if no aggregate location is provided.
1078
1079 void emitArrayDestroy(mlir::Value begin, mlir::Value numElements,
1080 QualType elementType, CharUnits elementAlign,
1081 Destroyer *destroyer);
1082
1083 mlir::Value emitArrayLength(const clang::ArrayType *arrayType,
1084 QualType &baseType, Address &addr);
1086
1088 LValueBaseInfo *baseInfo = nullptr);
1089
1090 mlir::LogicalResult emitAsmStmt(const clang::AsmStmt &s);
1091
1093 void emitAtomicInit(Expr *init, LValue dest);
1094
1096 mlir::OpBuilder::InsertPoint ip = {});
1097
1098 /// Emit code and set up symbol table for a variable declaration with auto,
1099 /// register, or no storage class specifier. These turn into simple stack
1100 /// objects, globals depending on target.
1101 void emitAutoVarDecl(const clang::VarDecl &d);
1102
1103 void emitAutoVarCleanups(const AutoVarEmission &emission);
1104 /// Emit the initializer for an allocated variable. If this call is not
1105 /// associated with the call to emitAutoVarAlloca (as the address of the
1106 /// emission is not directly an alloca), the allocatedSeparately parameter can
1107 /// be used to suppress the assertions. However, this should only be used in
1108 /// extreme cases, as it doesn't properly reflect the language/AST.
1109 void emitAutoVarInit(const AutoVarEmission &emission);
1110 void emitAutoVarTypeCleanup(const AutoVarEmission &emission,
1112
1113 void maybeEmitDeferredVarDeclInit(const VarDecl *vd);
1114
1115 void emitBaseInitializer(mlir::Location loc, const CXXRecordDecl *classDecl,
1116 CXXCtorInitializer *baseInit);
1117
1119
1120 mlir::LogicalResult emitBreakStmt(const clang::BreakStmt &s);
1121
1122 RValue emitBuiltinExpr(const clang::GlobalDecl &gd, unsigned builtinID,
1124
1125 RValue emitCall(const CIRGenFunctionInfo &funcInfo,
1127 const CallArgList &args, cir::CIRCallOpInterface *callOp,
1128 mlir::Location loc);
1131 const CallArgList &args,
1132 cir::CIRCallOpInterface *callOrTryCall = nullptr) {
1133 assert(currSrcLoc && "source location must have been set");
1134 return emitCall(funcInfo, callee, returnValue, args, callOrTryCall,
1135 *currSrcLoc);
1136 }
1137
1138 RValue emitCall(clang::QualType calleeTy, const CIRGenCallee &callee,
1140 void emitCallArg(CallArgList &args, const clang::Expr *e,
1141 clang::QualType argType);
1142 void emitCallArgs(
1143 CallArgList &args, PrototypeWrapper prototype,
1144 llvm::iterator_range<clang::CallExpr::const_arg_iterator> argRange,
1145 AbstractCallee callee = AbstractCallee(), unsigned paramsToSkip = 0);
1150
1151 template <typename T>
1152 mlir::LogicalResult emitCaseDefaultCascade(const T *stmt, mlir::Type condType,
1153 mlir::ArrayAttr value,
1154 cir::CaseOpKind kind,
1155 bool buildingTopLevelCase);
1156
1157 mlir::LogicalResult emitCaseStmt(const clang::CaseStmt &s,
1158 mlir::Type condType,
1159 bool buildingTopLevelCase);
1160
1161 LValue emitCastLValue(const CastExpr *e);
1162
1163 /// Emits an argument for a call to a `__builtin_assume`. If the builtin
1164 /// sanitizer is enabled, a runtime check is also emitted.
1165 mlir::Value emitCheckedArgForAssume(const Expr *e);
1166
1167 /// Emit a conversion from the specified complex type to the specified
1168 /// destination type, where the destination type is an LLVM scalar type.
1169 mlir::Value emitComplexToScalarConversion(mlir::Value src, QualType srcTy,
1170 QualType dstTy, SourceLocation loc);
1171
1174
1176
1177 void emitDestroy(Address addr, QualType type, Destroyer *destroyer);
1178
1180
1181 mlir::LogicalResult emitContinueStmt(const clang::ContinueStmt &s);
1182
1184 AggValueSlot dest);
1185
1188 Address arrayBegin, const CXXConstructExpr *e,
1189 bool newPointerIsChecked,
1190 bool zeroInitialize = false);
1192 mlir::Value numElements, Address arrayBase,
1193 const CXXConstructExpr *e,
1194 bool newPointerIsChecked,
1195 bool zeroInitialize);
1197 clang::CXXCtorType type, bool forVirtualBase,
1198 bool delegating, AggValueSlot thisAVS,
1199 const clang::CXXConstructExpr *e);
1200
1202 clang::CXXCtorType type, bool forVirtualBase,
1203 bool delegating, Address thisAddr,
1205
1206 void emitCXXDeleteExpr(const CXXDeleteExpr *e);
1207
1209 bool forVirtualBase, bool delegating,
1210 Address thisAddr, QualType thisTy);
1211
1213 mlir::Value thisVal, QualType thisTy,
1214 mlir::Value implicitParam,
1215 QualType implicitParamTy, const CallExpr *e);
1216
1217 mlir::LogicalResult emitCXXForRangeStmt(const CXXForRangeStmt &s,
1219
1222
1224 const clang::CXXMethodDecl *md, const CIRGenCallee &callee,
1225 ReturnValueSlot returnValue, mlir::Value thisPtr,
1226 mlir::Value implicitParam, clang::QualType implicitParamTy,
1227 const clang::CallExpr *ce, CallArgList *rtlArgs);
1228
1230 const clang::CallExpr *ce, const clang::CXXMethodDecl *md,
1231 ReturnValueSlot returnValue, bool hasQualifier,
1232 clang::NestedNameSpecifier qualifier, bool isArrow,
1233 const clang::Expr *base);
1234
1235 mlir::Value emitCXXNewExpr(const CXXNewExpr *e);
1236
1238 const CXXMethodDecl *md,
1240
1242
1243 void emitCXXThrowExpr(const CXXThrowExpr *e);
1244
1246 clang::CXXCtorType ctorType, FunctionArgList &args);
1247
1248 // It's important not to confuse this and emitDelegateCXXConstructorCall.
1249 // Delegating constructors are the C++11 feature. The constructor delegate
1250 // optimization is used to reduce duplication in the base and complete
1251 // constructors where they are substantially the same.
1253 const FunctionArgList &args);
1254
1255 void emitDeleteCall(const FunctionDecl *deleteFD, mlir::Value ptr,
1256 QualType deleteTy);
1257
1258 mlir::LogicalResult emitDoStmt(const clang::DoStmt &s);
1259
1260 /// Emit an expression as an initializer for an object (variable, field, etc.)
1261 /// at the given location. The expression is not necessarily the normal
1262 /// initializer for the object, and the address is not necessarily
1263 /// its normal location.
1264 ///
1265 /// \param init the initializing expression
1266 /// \param d the object to act as if we're initializing
1267 /// \param lvalue the lvalue to initialize
1268 /// \param capturedByInit true if \p d is a __block variable whose address is
1269 /// potentially changed by the initializer
1270 void emitExprAsInit(const clang::Expr *init, const clang::ValueDecl *d,
1271 LValue lvalue, bool capturedByInit = false);
1272
1273 mlir::LogicalResult emitFunctionBody(const clang::Stmt *body);
1274
1275 mlir::LogicalResult emitGotoStmt(const clang::GotoStmt &s);
1276
1278
1280 clang::Expr *init);
1281
1282 mlir::Value emitPromotedComplexExpr(const Expr *e, QualType promotionType);
1283
1284 mlir::Value emitPromotedScalarExpr(const Expr *e, QualType promotionType);
1285
1286 mlir::Value emitPromotedValue(mlir::Value result, QualType promotionType);
1287
1288 void emitReturnOfRValue(mlir::Location loc, RValue rv, QualType ty);
1289
1290 /// Emit the computation of the specified expression of scalar type.
1291 mlir::Value emitScalarExpr(const clang::Expr *e);
1292
1293 mlir::Value emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv,
1294 cir::UnaryOpKind kind, bool isPre);
1295
1296 /// Build a debug stoppoint if we are emitting debug info.
1297 void emitStopPoint(const Stmt *s);
1298
1299 // Build CIR for a statement. useCurrentScope should be true if no
1300 // new scopes need be created when finding a compound statement.
1301 mlir::LogicalResult emitStmt(const clang::Stmt *s, bool useCurrentScope,
1302 llvm::ArrayRef<const Attr *> attrs = {});
1303
1304 mlir::LogicalResult emitSimpleStmt(const clang::Stmt *s,
1305 bool useCurrentScope);
1306
1307 mlir::LogicalResult emitForStmt(const clang::ForStmt &s);
1308
1309 void emitForwardingCallToLambda(const CXXMethodDecl *lambdaCallOperator,
1310 CallArgList &callArgs);
1311
1312 /// Emit the computation of the specified expression of complex type,
1313 /// returning the result.
1314 mlir::Value emitComplexExpr(const Expr *e);
1315
1316 void emitComplexExprIntoLValue(const Expr *e, LValue dest, bool isInit);
1317
1318 mlir::Value emitComplexPrePostIncDec(const UnaryOperator *e, LValue lv,
1319 cir::UnaryOpKind op, bool isPre);
1320
1324 mlir::Value &result);
1325
1326 mlir::LogicalResult
1327 emitCompoundStmt(const clang::CompoundStmt &s, Address *lastValue = nullptr,
1329
1330 mlir::LogicalResult
1332 Address *lastValue = nullptr,
1334
1335 void emitDecl(const clang::Decl &d, bool evaluateConditionDecl = false);
1336 mlir::LogicalResult emitDeclStmt(const clang::DeclStmt &s);
1338
1339 mlir::LogicalResult emitDefaultStmt(const clang::DefaultStmt &s,
1340 mlir::Type condType,
1341 bool buildingTopLevelCase);
1342
1344 clang::CXXCtorType ctorType,
1345 const FunctionArgList &args,
1347
1348 /// We are performing a delegate call; that is, the current function is
1349 /// delegating to another one. Produce a r-value suitable for passing the
1350 /// given parameter.
1351 void emitDelegateCallArg(CallArgList &args, const clang::VarDecl *param,
1353
1354 /// Emit an `if` on a boolean condition to the specified blocks.
1355 /// FIXME: Based on the condition, this might try to simplify the codegen of
1356 /// the conditional based on the branch.
1357 /// In the future, we may apply code generation simplifications here,
1358 /// similar to those used in classic LLVM codegen
1359 /// See `EmitBranchOnBoolExpr` for inspiration.
1360 mlir::LogicalResult emitIfOnBoolExpr(const clang::Expr *cond,
1361 const clang::Stmt *thenS,
1362 const clang::Stmt *elseS);
1363 cir::IfOp emitIfOnBoolExpr(const clang::Expr *cond,
1364 BuilderCallbackRef thenBuilder,
1365 mlir::Location thenLoc,
1366 BuilderCallbackRef elseBuilder,
1367 std::optional<mlir::Location> elseLoc = {});
1368
1369 mlir::Value emitOpOnBoolExpr(mlir::Location loc, const clang::Expr *cond);
1370
1371 mlir::LogicalResult emitLabel(const clang::LabelDecl &d);
1372 mlir::LogicalResult emitLabelStmt(const clang::LabelStmt &s);
1373
1376
1377 mlir::LogicalResult emitIfStmt(const clang::IfStmt &s);
1378
1379 /// Emit code to compute the specified expression,
1380 /// ignoring the result.
1381 void emitIgnoredExpr(const clang::Expr *e);
1382
1383 RValue emitLoadOfBitfieldLValue(LValue lv, SourceLocation loc);
1384
1385 /// Load a complex number from the specified l-value.
1386 mlir::Value emitLoadOfComplex(LValue src, SourceLocation loc);
1387
1388 /// Given an expression that represents a value lvalue, this method emits
1389 /// the address of the lvalue, then loads the result as an rvalue,
1390 /// returning the rvalue.
1391 RValue emitLoadOfLValue(LValue lv, SourceLocation loc);
1392
1393 Address emitLoadOfReference(LValue refLVal, mlir::Location loc,
1394 LValueBaseInfo *pointeeBaseInfo);
1395 LValue emitLoadOfReferenceLValue(Address refAddr, mlir::Location loc,
1396 QualType refTy, AlignmentSource source);
1397
1398 /// EmitLoadOfScalar - Load a scalar value from an address, taking
1399 /// care to appropriately convert from the memory representation to
1400 /// the LLVM value representation. The l-value must be a simple
1401 /// l-value.
1402 mlir::Value emitLoadOfScalar(LValue lvalue, SourceLocation loc);
1403 mlir::Value emitLoadOfScalar(Address addr, bool isVolatile, QualType ty,
1404 SourceLocation loc, LValueBaseInfo baseInfo);
1405
1406 /// Emit code to compute a designator that specifies the location
1407 /// of the expression.
1408 /// FIXME: document this function better.
1409 LValue emitLValue(const clang::Expr *e);
1410 LValue emitLValueForBitField(LValue base, const FieldDecl *field);
1411 LValue emitLValueForField(LValue base, const clang::FieldDecl *field);
1412
1413 LValue emitLValueForLambdaField(const FieldDecl *field);
1414 LValue emitLValueForLambdaField(const FieldDecl *field,
1415 mlir::Value thisValue);
1416
1417 /// Like emitLValueForField, excpet that if the Field is a reference, this
1418 /// will return the address of the reference and not the address of the value
1419 /// stored in the reference.
1420 LValue emitLValueForFieldInitialization(LValue base,
1421 const clang::FieldDecl *field,
1422 llvm::StringRef fieldName);
1423
1425
1426 LValue emitMemberExpr(const MemberExpr *e);
1427
1428 /// Given an expression with a pointer type, emit the value and compute our
1429 /// best estimate of the alignment of the pointee.
1430 ///
1431 /// One reasonable way to use this information is when there's a language
1432 /// guarantee that the pointer must be aligned to some stricter value, and
1433 /// we're simply trying to ensure that sufficiently obvious uses of under-
1434 /// aligned objects don't get miscompiled; for example, a placement new
1435 /// into the address of a local variable. In such a case, it's quite
1436 /// reasonable to just ignore the returned alignment when it isn't from an
1437 /// explicit source.
1439 LValueBaseInfo *baseInfo = nullptr);
1440
1441 /// Emits a reference binding to the passed in expression.
1442 RValue emitReferenceBindingToExpr(const Expr *e);
1443
1444 mlir::LogicalResult emitReturnStmt(const clang::ReturnStmt &s);
1445
1446 RValue emitRotate(const CallExpr *e, bool isRotateLeft);
1447
1448 mlir::Value emitScalarConstant(const ConstantEmission &constant, Expr *e);
1449
1450 /// Emit a conversion from the specified type to the specified destination
1451 /// type, both of which are CIR scalar types.
1452 mlir::Value emitScalarConversion(mlir::Value src, clang::QualType srcType,
1453 clang::QualType dstType,
1455
1456 void emitScalarInit(const clang::Expr *init, mlir::Location loc,
1457 LValue lvalue, bool capturedByInit = false);
1458
1459 void emitStaticVarDecl(const VarDecl &d, cir::GlobalLinkageKind linkage);
1460
1461 void emitStoreOfComplex(mlir::Location loc, mlir::Value v, LValue dest,
1462 bool isInit);
1463
1464 void emitStoreOfScalar(mlir::Value value, Address addr, bool isVolatile,
1465 clang::QualType ty, bool isInit = false,
1466 bool isNontemporal = false);
1467 void emitStoreOfScalar(mlir::Value value, LValue lvalue, bool isInit);
1468
1469 /// Store the specified rvalue into the specified
1470 /// lvalue, where both are guaranteed to the have the same type, and that type
1471 /// is 'Ty'.
1472 void emitStoreThroughLValue(RValue src, LValue dst, bool isInit = false);
1473
1474 mlir::Value emitStoreThroughBitfieldLValue(RValue src, LValue dstresult);
1475
1476 LValue emitStringLiteralLValue(const StringLiteral *e);
1477
1478 mlir::LogicalResult emitSwitchBody(const clang::Stmt *s);
1479 mlir::LogicalResult emitSwitchCase(const clang::SwitchCase &s,
1480 bool buildingTopLevelCase);
1481 mlir::LogicalResult emitSwitchStmt(const clang::SwitchStmt &s);
1482
1483 /// Given a value and its clang type, returns the value casted to its memory
1484 /// representation.
1485 /// Note: CIR defers most of the special casting to the final lowering passes
1486 /// to conserve the high level information.
1487 mlir::Value emitToMemory(mlir::Value value, clang::QualType ty);
1488
1489 /// Emit a trap instruction, which is used to abort the program in an abnormal
1490 /// way, usually for debugging purposes.
1491 /// \p createNewBlock indicates whether to create a new block for the IR
1492 /// builder. Since the `cir.trap` operation is a terminator, operations that
1493 /// follow a trap cannot be emitted after `cir.trap` in the same block. To
1494 /// ensure these operations get emitted successfully, you need to create a new
1495 /// dummy block and set the insertion point there before continuing from the
1496 /// trap operation.
1497 void emitTrap(mlir::Location loc, bool createNewBlock);
1498
1499 LValue emitUnaryOpLValue(const clang::UnaryOperator *e);
1500
1501 mlir::Value emitUnPromotedValue(mlir::Value result, QualType unPromotionType);
1502
1503 /// Emit a reached-unreachable diagnostic if \p loc is valid and runtime
1504 /// checking is enabled. Otherwise, just emit an unreachable instruction.
1505 /// \p createNewBlock indicates whether to create a new block for the IR
1506 /// builder. Since the `cir.unreachable` operation is a terminator, operations
1507 /// that follow an unreachable point cannot be emitted after `cir.unreachable`
1508 /// in the same block. To ensure these operations get emitted successfully,
1509 /// you need to create a dummy block and set the insertion point there before
1510 /// continuing from the unreachable point.
1511 void emitUnreachable(clang::SourceLocation loc, bool createNewBlock);
1512
1513 /// This method handles emission of any variable declaration
1514 /// inside a function, including static vars etc.
1515 void emitVarDecl(const clang::VarDecl &d);
1516
1518
1519 mlir::LogicalResult emitWhileStmt(const clang::WhileStmt &s);
1520
1521 /// Given an assignment `*lhs = rhs`, emit a test that checks if \p rhs is
1522 /// nonnull, if 1\p LHS is marked _Nonnull.
1523 void emitNullabilityCheck(LValue lhs, mlir::Value rhs,
1525
1526 /// An object to manage conditionally-evaluated expressions.
1528 CIRGenFunction &cgf;
1529 mlir::OpBuilder::InsertPoint insertPt;
1530
1531 public:
1533 : cgf(cgf), insertPt(cgf.builder.saveInsertionPoint()) {}
1534 ConditionalEvaluation(CIRGenFunction &cgf, mlir::OpBuilder::InsertPoint ip)
1535 : cgf(cgf), insertPt(ip) {}
1536
1538 assert(cgf.outermostConditional != this);
1539 if (!cgf.outermostConditional)
1540 cgf.outermostConditional = this;
1541 }
1542
1544 assert(cgf.outermostConditional != nullptr);
1545 if (cgf.outermostConditional == this)
1546 cgf.outermostConditional = nullptr;
1547 }
1548
1549 /// Returns the insertion point which will be executed prior to each
1550 /// evaluation of the conditional code. In LLVM OG, this method
1551 /// is called getStartingBlock.
1552 mlir::OpBuilder::InsertPoint getInsertPoint() const { return insertPt; }
1553 };
1554
1556 std::optional<LValue> lhs{}, rhs{};
1557 mlir::Value result{};
1558 };
1559
1560 // Return true if we're currently emitting one branch or the other of a
1561 // conditional expression.
1562 bool isInConditionalBranch() const { return outermostConditional != nullptr; }
1563
1564 void setBeforeOutermostConditional(mlir::Value value, Address addr) {
1565 assert(isInConditionalBranch());
1566 {
1567 mlir::OpBuilder::InsertionGuard guard(builder);
1568 builder.restoreInsertionPoint(outermostConditional->getInsertPoint());
1569 builder.createStore(
1570 value.getLoc(), value, addr, /*isVolatile=*/false,
1571 mlir::IntegerAttr::get(
1572 mlir::IntegerType::get(value.getContext(), 64),
1573 (uint64_t)addr.getAlignment().getAsAlign().value()));
1574 }
1575 }
1576
1577 // Points to the outermost active conditional control. This is used so that
1578 // we know if a temporary should be destroyed conditionally.
1580
1581 /// An RAII object to record that we're evaluating a statement
1582 /// expression.
1584 CIRGenFunction &cgf;
1585
1586 /// We have to save the outermost conditional: cleanups in a
1587 /// statement expression aren't conditional just because the
1588 /// StmtExpr is.
1589 ConditionalEvaluation *savedOutermostConditional;
1590
1591 public:
1593 : cgf(cgf), savedOutermostConditional(cgf.outermostConditional) {
1594 cgf.outermostConditional = nullptr;
1595 }
1596
1598 cgf.outermostConditional = savedOutermostConditional;
1599 }
1600 };
1601
1602 template <typename FuncTy>
1604 const FuncTy &branchGenFunc);
1605
1606 mlir::Value emitTernaryOnBoolExpr(const clang::Expr *cond, mlir::Location loc,
1607 const clang::Stmt *thenS,
1608 const clang::Stmt *elseS);
1609
1610 /// Build a "reference" to a va_list; this is either the address or the value
1611 /// of the expression, depending on how va_list is defined.
1612 Address emitVAListRef(const Expr *e);
1613
1614 /// Emits the start of a CIR variable-argument operation (`cir.va_start`)
1615 ///
1616 /// \param vaList A reference to the \c va_list as emitted by either
1617 /// \c emitVAListRef or \c emitMSVAListRef.
1618 ///
1619 /// \param count The number of arguments in \c vaList
1620 void emitVAStart(mlir::Value vaList, mlir::Value count);
1621
1622 /// Emits the end of a CIR variable-argument operation (`cir.va_start`)
1623 ///
1624 /// \param vaList A reference to the \c va_list as emitted by either
1625 /// \c emitVAListRef or \c emitMSVAListRef.
1626 void emitVAEnd(mlir::Value vaList);
1627
1628 /// Generate code to get an argument from the passed in pointer
1629 /// and update it accordingly.
1630 ///
1631 /// \param ve The \c VAArgExpr for which to generate code.
1632 ///
1633 /// \param vaListAddr Receives a reference to the \c va_list as emitted by
1634 /// either \c emitVAListRef or \c emitMSVAListRef.
1635 ///
1636 /// \returns SSA value with the argument.
1637 mlir::Value emitVAArg(VAArgExpr *ve);
1638
1639 /// ----------------------
1640 /// CIR build helpers
1641 /// -----------------
1642public:
1643 cir::AllocaOp createTempAlloca(mlir::Type ty, mlir::Location loc,
1644 const Twine &name = "tmp",
1645 mlir::Value arraySize = nullptr,
1646 bool insertIntoFnEntryBlock = false);
1647 cir::AllocaOp createTempAlloca(mlir::Type ty, mlir::Location loc,
1648 const Twine &name = "tmp",
1649 mlir::OpBuilder::InsertPoint ip = {},
1650 mlir::Value arraySize = nullptr);
1651 Address createTempAlloca(mlir::Type ty, CharUnits align, mlir::Location loc,
1652 const Twine &name = "tmp",
1653 mlir::Value arraySize = nullptr,
1654 Address *alloca = nullptr,
1655 mlir::OpBuilder::InsertPoint ip = {});
1656 Address createTempAllocaWithoutCast(mlir::Type ty, CharUnits align,
1657 mlir::Location loc,
1658 const Twine &name = "tmp",
1659 mlir::Value arraySize = nullptr,
1660 mlir::OpBuilder::InsertPoint ip = {});
1661
1662 /// Create a temporary memory object of the given type, with
1663 /// appropriate alignmen and cast it to the default address space. Returns
1664 /// the original alloca instruction by \p Alloca if it is not nullptr.
1665 Address createMemTemp(QualType t, mlir::Location loc,
1666 const Twine &name = "tmp", Address *alloca = nullptr,
1667 mlir::OpBuilder::InsertPoint ip = {});
1668 Address createMemTemp(QualType t, CharUnits align, mlir::Location loc,
1669 const Twine &name = "tmp", Address *alloca = nullptr,
1670 mlir::OpBuilder::InsertPoint ip = {});
1671
1672 //===--------------------------------------------------------------------===//
1673 // OpenACC Emission
1674 //===--------------------------------------------------------------------===//
1675private:
1676 template <typename Op>
1677 Op emitOpenACCOp(mlir::Location start, OpenACCDirectiveKind dirKind,
1678 SourceLocation dirLoc,
1679 llvm::ArrayRef<const OpenACCClause *> clauses);
1680 // Function to do the basic implementation of an operation with an Associated
1681 // Statement. Models AssociatedStmtConstruct.
1682 template <typename Op, typename TermOp>
1683 mlir::LogicalResult emitOpenACCOpAssociatedStmt(
1684 mlir::Location start, mlir::Location end, OpenACCDirectiveKind dirKind,
1685 SourceLocation dirLoc, llvm::ArrayRef<const OpenACCClause *> clauses,
1686 const Stmt *associatedStmt);
1687
1688 template <typename Op, typename TermOp>
1689 mlir::LogicalResult emitOpenACCOpCombinedConstruct(
1690 mlir::Location start, mlir::Location end, OpenACCDirectiveKind dirKind,
1691 SourceLocation dirLoc, llvm::ArrayRef<const OpenACCClause *> clauses,
1692 const Stmt *loopStmt);
1693
1694 template <typename Op>
1695 void emitOpenACCClauses(Op &op, OpenACCDirectiveKind dirKind,
1696 SourceLocation dirLoc,
1697 ArrayRef<const OpenACCClause *> clauses);
1698 // The second template argument doesn't need to be a template, since it should
1699 // always be an mlir::acc::LoopOp, but as this is a template anyway, we make
1700 // it a template argument as this way we can avoid including the OpenACC MLIR
1701 // headers here. We will count on linker failures/explicit instantiation to
1702 // ensure we don't mess this up, but it is only called from 1 place, and
1703 // instantiated 3x.
1704 template <typename ComputeOp, typename LoopOp>
1705 void emitOpenACCClauses(ComputeOp &op, LoopOp &loopOp,
1706 OpenACCDirectiveKind dirKind, SourceLocation dirLoc,
1707 ArrayRef<const OpenACCClause *> clauses);
1708
1709 // The OpenACC LoopOp requires that we have auto, seq, or independent on all
1710 // LoopOp operations for the 'none' device type case. This function checks if
1711 // the LoopOp has one, else it updates it to have one.
1712 void updateLoopOpParallelism(mlir::acc::LoopOp &op, bool isOrphan,
1714
1715 // The OpenACC 'cache' construct actually applies to the 'loop' if present. So
1716 // keep track of the 'loop' so that we can add the cache vars to it correctly.
1717 mlir::acc::LoopOp *activeLoopOp = nullptr;
1718
1719 struct ActiveOpenACCLoopRAII {
1720 CIRGenFunction &cgf;
1721 mlir::acc::LoopOp *oldLoopOp;
1722
1723 ActiveOpenACCLoopRAII(CIRGenFunction &cgf, mlir::acc::LoopOp *newOp)
1724 : cgf(cgf), oldLoopOp(cgf.activeLoopOp) {
1725 cgf.activeLoopOp = newOp;
1726 }
1727 ~ActiveOpenACCLoopRAII() { cgf.activeLoopOp = oldLoopOp; }
1728 };
1729
1730 // Keep track of the last place we inserted a 'recipe' so that we can insert
1731 // the next one in lexical order.
1732 mlir::OpBuilder::InsertPoint lastRecipeLocation;
1733
1734public:
1735 // Helper type used to store the list of important information for a 'data'
1736 // clause variable, or a 'cache' variable reference.
1738 mlir::Location beginLoc;
1739 mlir::Value varValue;
1740 std::string name;
1741 // The type of the original variable reference: that is, after 'bounds' have
1742 // removed pointers/array types/etc. So in the case of int arr[5], and a
1743 // private(arr[1]), 'origType' is 'int', but 'baseType' is 'int[5]'.
1747 // The list of types that we found when going through the bounds, which we
1748 // can use to properly set the alloca section.
1750 };
1751
1752 // Gets the collection of info required to lower and OpenACC clause or cache
1753 // construct variable reference.
1755 // Helper function to emit the integer expressions as required by an OpenACC
1756 // clause/construct.
1757 mlir::Value emitOpenACCIntExpr(const Expr *intExpr);
1758 // Helper function to emit an integer constant as an mlir int type, used for
1759 // constants in OpenACC constructs/clauses.
1760 mlir::Value createOpenACCConstantInt(mlir::Location loc, unsigned width,
1761 int64_t value);
1762
1763 mlir::LogicalResult
1765 mlir::LogicalResult emitOpenACCLoopConstruct(const OpenACCLoopConstruct &s);
1766 mlir::LogicalResult
1768 mlir::LogicalResult emitOpenACCDataConstruct(const OpenACCDataConstruct &s);
1769 mlir::LogicalResult
1771 mlir::LogicalResult
1773 mlir::LogicalResult
1775 mlir::LogicalResult emitOpenACCWaitConstruct(const OpenACCWaitConstruct &s);
1776 mlir::LogicalResult emitOpenACCInitConstruct(const OpenACCInitConstruct &s);
1777 mlir::LogicalResult
1779 mlir::LogicalResult emitOpenACCSetConstruct(const OpenACCSetConstruct &s);
1780 mlir::LogicalResult
1782 mlir::LogicalResult
1784 mlir::LogicalResult emitOpenACCCacheConstruct(const OpenACCCacheConstruct &s);
1785
1788
1789 /// Create a temporary memory object for the given aggregate type.
1790 AggValueSlot createAggTemp(QualType ty, mlir::Location loc,
1791 const Twine &name = "tmp",
1792 Address *alloca = nullptr) {
1794 return AggValueSlot::forAddr(
1795 createMemTemp(ty, loc, name, alloca), ty.getQualifiers(),
1798 }
1799
1800private:
1801 QualType getVarArgType(const Expr *arg);
1802};
1803
1804} // namespace clang::CIRGen
1805
1806#endif
Defines the clang::ASTContext interface.
llvm::function_ref< void(mlir::OpBuilder &, mlir::Location)> BuilderCallbackRef
Definition CIRDialect.h:37
Defines the clang::Expr interface and subclasses for C++ expressions.
C Language Family Type Representation.
__device__ __2f16 b
__device__ __2f16 float __ockl_bool s
__device__ __2f16 float c
This class represents a 'loop' construct. The 'loop' construct applies to a 'for' loop (or range-for ...
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:220
AbstractConditionalOperator - An abstract base class for ConditionalOperator and BinaryConditionalOpe...
Definition Expr.h:4287
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Definition Expr.h:2721
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition TypeBase.h:3722
AsmStmt is the base class for GCCAsmStmt and MSAsmStmt.
Definition Stmt.h:3236
AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*, __atomic_load,...
Definition Expr.h:6814
BinaryConditionalOperator - The GNU extension to the conditional operator which allows the middle ope...
Definition Expr.h:4387
OpaqueValueExpr * getOpaqueValue() const
getOpaqueValue - Return the opaque value placeholder.
Definition Expr.h:4425
Expr * getCommon() const
getCommon - Return the common expression, written to the left of the condition.
Definition Expr.h:4422
A builtin binary operation expression such as "x + y" or "x <= y".
Definition Expr.h:3972
BreakStmt - This represents a break.
Definition Stmt.h:3135
mlir::Value getPointer() const
Definition Address.h:81
static Address invalid()
Definition Address.h:66
clang::CharUnits getAlignment() const
Definition Address.h:109
An aggregate value slot.
static AggValueSlot forAddr(Address addr, clang::Qualifiers quals, IsDestructed_t isDestructed, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed)
static AggValueSlot ignored()
Returns an aggregate value slot indicating that the aggregate value is being ignored.
AbstractCallee(const clang::FunctionDecl *fd)
const clang::ParmVarDecl * getParamDecl(unsigned I) const
CXXDefaultInitExprScope(CIRGenFunction &cgf, const CXXDefaultInitExpr *e)
An object to manage conditionally-evaluated expressions.
ConditionalEvaluation(CIRGenFunction &cgf, mlir::OpBuilder::InsertPoint ip)
mlir::OpBuilder::InsertPoint getInsertPoint() const
Returns the insertion point which will be executed prior to each evaluation of the conditional code.
static ConstantEmission forReference(mlir::TypedAttr c)
static ConstantEmission forValue(mlir::TypedAttr c)
LValue getReferenceLValue(CIRGenFunction &cgf, Expr *refExpr) const
DeclMapRevertingRAII(CIRGenFunction &cgf, const VarDecl *vd)
FieldConstructionScope(CIRGenFunction &cgf, Address thisAddr)
A non-RAII class containing all the information about a bound opaque value.
static OpaqueValueMappingData bind(CIRGenFunction &cgf, const OpaqueValueExpr *ov, const LValue &lv)
static OpaqueValueMappingData bind(CIRGenFunction &cgf, const OpaqueValueExpr *ov, const RValue &rv)
static OpaqueValueMappingData bind(CIRGenFunction &cgf, const OpaqueValueExpr *ov, const Expr *e)
OpaqueValueMapping(CIRGenFunction &cgf, const OpaqueValueExpr *opaqueValue, RValue rvalue)
OpaqueValueMapping(CIRGenFunction &cgf, const OpaqueValueExpr *opaqueValue, LValue lvalue)
OpaqueValueMapping(CIRGenFunction &cgf, const AbstractConditionalOperator *op)
Build the opaque value mapping for the given conditional operator if it's the GNU ?
OpaqueValueMapping(CIRGenFunction &cgf, const OpaqueValueExpr *ov)
Build the opaque value mapping for an OpaqueValueExpr whose source expression is set to the expressio...
RunCleanupsScope(CIRGenFunction &cgf)
Enter a new cleanup scope.
void forceCleanup()
Force the emission of cleanups now, instead of waiting until this object is destroyed.
~RunCleanupsScope()
Exit this cleanup scope, emitting any accumulated cleanups.
void restore()
Can be used to restore the state early, before the dtor is run.
SourceLocRAIIObject(CIRGenFunction &cgf, mlir::Location value)
static bool isConstructorDelegationValid(const clang::CXXConstructorDecl *ctor)
Checks whether the given constructor is a valid subject for the complete-to-base constructor delegati...
static bool hasScalarEvaluationKind(clang::QualType type)
void emitOpenACCRoutine(const OpenACCRoutineDecl &d)
void emitLambdaDelegatingInvokeBody(const CXXMethodDecl *md)
mlir::Value emitComplexToScalarConversion(mlir::Value src, QualType srcTy, QualType dstTy, SourceLocation loc)
Emit a conversion from the specified complex type to the specified destination type,...
void emitCallArgs(CallArgList &args, PrototypeWrapper prototype, llvm::iterator_range< clang::CallExpr::const_arg_iterator > argRange, AbstractCallee callee=AbstractCallee(), unsigned paramsToSkip=0)
mlir::Type convertType(clang::QualType t)
cir::GlobalOp addInitializerToStaticVarDecl(const VarDecl &d, cir::GlobalOp gv, cir::GetGlobalOp gvAddr)
Add the initializer for 'd' to the global variable that has already been created for it.
mlir::Value emitCheckedArgForAssume(const Expr *e)
Emits an argument for a call to a __builtin_assume.
mlir::LogicalResult emitDoStmt(const clang::DoStmt &s)
static cir::TypeEvaluationKind getEvaluationKind(clang::QualType type)
Return the cir::TypeEvaluationKind of QualType type.
clang::GlobalDecl curGD
The GlobalDecl for the current function being compiled or the global variable currently being initial...
clang::CurrentSourceLocExprScope::SourceLocExprScopeGuard SourceLocExprScopeGuard
RValue convertTempToRValue(Address addr, clang::QualType type, clang::SourceLocation loc)
Given the address of a temporary variable, produce an r-value of its type.
mlir::LogicalResult emitOpenACCDataConstruct(const OpenACCDataConstruct &s)
AutoVarEmission emitAutoVarAlloca(const clang::VarDecl &d, mlir::OpBuilder::InsertPoint ip={})
mlir::Value emitPromotedValue(mlir::Value result, QualType promotionType)
void emitAutoVarTypeCleanup(const AutoVarEmission &emission, clang::QualType::DestructionKind dtorKind)
Enter a destroy cleanup for the given local variable.
ImplicitParamDecl * cxxabiThisDecl
CXXThisDecl - When generating code for a C++ member function, this will hold the implicit 'this' decl...
EHScopeStack::stable_iterator prologueCleanupDepth
The cleanup depth enclosing all the cleanups associated with the parameters.
mlir::LogicalResult emitOpenACCCombinedConstruct(const OpenACCCombinedConstruct &s)
mlir::LogicalResult emitOpenACCWaitConstruct(const OpenACCWaitConstruct &s)
cir::FuncOp generateCode(clang::GlobalDecl gd, cir::FuncOp fn, cir::FuncType funcType)
CIRGenTypes & getTypes() const
Address emitPointerWithAlignment(const clang::Expr *expr, LValueBaseInfo *baseInfo=nullptr)
Given an expression with a pointer type, emit the value and compute our best estimate of the alignmen...
llvm::ScopedHashTable< const clang::Decl *, mlir::Value > SymTableTy
The symbol table maps a variable name to a value in the current scope.
void emitVariablyModifiedType(QualType ty)
RValue emitLoadOfLValue(LValue lv, SourceLocation loc)
Given an expression that represents a value lvalue, this method emits the address of the lvalue,...
const clang::LangOptions & getLangOpts() const
cir::AllocaOp createTempAlloca(mlir::Type ty, mlir::Location loc, const Twine &name="tmp", mlir::Value arraySize=nullptr, bool insertIntoFnEntryBlock=false)
This creates an alloca and inserts it into the entry block if ArraySize is nullptr,...
void emitTrap(mlir::Location loc, bool createNewBlock)
Emit a trap instruction, which is used to abort the program in an abnormal way, usually for debugging...
void emitForwardingCallToLambda(const CXXMethodDecl *lambdaCallOperator, CallArgList &callArgs)
mlir::Block * getCurFunctionEntryBlock()
RValue emitCXXMemberCallExpr(const clang::CXXMemberCallExpr *e, ReturnValueSlot returnValue)
mlir::LogicalResult emitOpenACCUpdateConstruct(const OpenACCUpdateConstruct &s)
LValue emitLValueForBitField(LValue base, const FieldDecl *field)
mlir::LogicalResult emitIfOnBoolExpr(const clang::Expr *cond, const clang::Stmt *thenS, const clang::Stmt *elseS)
Emit an if on a boolean condition to the specified blocks.
LValue emitScalarCompoundAssignWithComplex(const CompoundAssignOperator *e, mlir::Value &result)
Address cxxDefaultInitExprThis
The value of 'this' to sue when evaluating CXXDefaultInitExprs within this expression.
void emitStaticVarDecl(const VarDecl &d, cir::GlobalLinkageKind linkage)
mlir::Value emitComplexExpr(const Expr *e)
Emit the computation of the specified expression of complex type, returning the result.
void setBeforeOutermostConditional(mlir::Value value, Address addr)
mlir::LogicalResult emitOpenACCCacheConstruct(const OpenACCCacheConstruct &s)
mlir::Value loadCXXThis()
Load the value for 'this'.
LValue makeNaturalAlignPointeeAddrLValue(mlir::Value v, clang::QualType t)
Given a value of type T* that may not be to a complete object, construct an l-vlaue withi the natural...
RValue emitCallExpr(const clang::CallExpr *e, ReturnValueSlot returnValue=ReturnValueSlot())
void emitDeleteCall(const FunctionDecl *deleteFD, mlir::Value ptr, QualType deleteTy)
LValue emitMemberExpr(const MemberExpr *e)
clang::CharUnits cxxThisAlignment
const TargetInfo & getTarget() const
llvm::DenseMap< const clang::Decl *, Address > DeclMapTy
LValue emitLValue(const clang::Expr *e)
Emit code to compute a designator that specifies the location of the expression.
Address makeNaturalAddressForPointer(mlir::Value ptr, QualType t, CharUnits alignment, bool forPointeeType=false, LValueBaseInfo *baseInfo=nullptr)
Construct an address with the natural alignment of T.
const clang::Decl * curFuncDecl
mlir::LogicalResult emitCXXForRangeStmt(const CXXForRangeStmt &s, llvm::ArrayRef< const Attr * > attrs)
LValue emitLValueForLambdaField(const FieldDecl *field)
RValue emitCall(const CIRGenFunctionInfo &funcInfo, const CIRGenCallee &callee, ReturnValueSlot returnValue, const CallArgList &args, cir::CIRCallOpInterface *callOrTryCall=nullptr)
mlir::Value evaluateExprAsBool(const clang::Expr *e)
Perform the usual unary conversions on the specified expression and compare the result against zero,...
bool isTrivialInitializer(const Expr *init)
Determine whether the given initializer is trivial in the sense that it requires no code to be genera...
void emitOpenACCDeclare(const OpenACCDeclareDecl &d)
Address getAddrOfLocalVar(const clang::VarDecl *vd)
Return the address of a local variable.
LValue makeNaturalAlignAddrLValue(mlir::Value val, QualType ty)
bool constantFoldsToSimpleInteger(const clang::Expr *cond, llvm::APSInt &resultInt, bool allowLabels=false)
If the specified expression does not fold to a constant, or if it does fold but contains a label,...
void emitStoreOfScalar(mlir::Value value, Address addr, bool isVolatile, clang::QualType ty, bool isInit=false, bool isNontemporal=false)
LValue emitComplexCompoundAssignmentLValue(const CompoundAssignOperator *e)
mlir::Value getVTTParameter(GlobalDecl gd, bool forVirtualBase, bool delegating)
Return the VTT parameter that should be passed to a base constructor/destructor with virtual bases.
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
void initializeVTablePointers(mlir::Location loc, const clang::CXXRecordDecl *rd)
mlir::Type convertType(const TypeDecl *t)
bool constantFoldsToBool(const clang::Expr *cond, bool &resultBool, bool allowLabels=false)
If the specified expression does not fold to a constant, or if it does but contains a label,...
mlir::Value emitOpOnBoolExpr(mlir::Location loc, const clang::Expr *cond)
TODO(cir): see EmitBranchOnBoolExpr for extra ideas).
void initializeVTablePointer(mlir::Location loc, const VPtr &vptr)
Address getAddressOfBaseClass(Address value, const CXXRecordDecl *derived, llvm::iterator_range< CastExpr::path_const_iterator > path, bool nullCheckValue, SourceLocation loc)
LValue emitStringLiteralLValue(const StringLiteral *e)
void emitAggregateStore(mlir::Value value, Address dest)
mlir::LogicalResult emitReturnStmt(const clang::ReturnStmt &s)
LValue emitLoadOfReferenceLValue(Address refAddr, mlir::Location loc, QualType refTy, AlignmentSource source)
void emitDelegateCXXConstructorCall(const clang::CXXConstructorDecl *ctor, clang::CXXCtorType ctorType, const FunctionArgList &args, clang::SourceLocation loc)
mlir::Value emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv, cir::UnaryOpKind kind, bool isPre)
ConditionalEvaluation * outermostConditional
mlir::LogicalResult emitOpenACCInitConstruct(const OpenACCInitConstruct &s)
void emitAnyExprToMem(const Expr *e, Address location, Qualifiers quals, bool isInitializer)
Emits the code necessary to evaluate an arbitrary expression into the given memory location.
RValue emitCXXMemberOrOperatorCall(const clang::CXXMethodDecl *md, const CIRGenCallee &callee, ReturnValueSlot returnValue, mlir::Value thisPtr, mlir::Value implicitParam, clang::QualType implicitParamTy, const clang::CallExpr *ce, CallArgList *rtlArgs)
LValue getOrCreateOpaqueLValueMapping(const OpaqueValueExpr *e)
Given an opaque value expression, return its LValue mapping if it exists, otherwise create one.
void emitBaseInitializer(mlir::Location loc, const CXXRecordDecl *classDecl, CXXCtorInitializer *baseInit)
RValue emitAtomicExpr(AtomicExpr *e)
void emitExprAsInit(const clang::Expr *init, const clang::ValueDecl *d, LValue lvalue, bool capturedByInit=false)
Emit an expression as an initializer for an object (variable, field, etc.) at the given location.
mlir::Value emitArrayLength(const clang::ArrayType *arrayType, QualType &baseType, Address &addr)
Computes the length of an array in elements, as well as the base element type and a properly-typed fi...
void emitNullInitialization(mlir::Location loc, Address destPtr, QualType ty)
mlir::LogicalResult emitOpenACCSetConstruct(const OpenACCSetConstruct &s)
RValue emitReferenceBindingToExpr(const Expr *e)
Emits a reference binding to the passed in expression.
void emitVAStart(mlir::Value vaList, mlir::Value count)
Emits the start of a CIR variable-argument operation (cir.va_start)
VPtrsVector getVTablePointers(const clang::CXXRecordDecl *vtableClass)
RValue emitAnyExpr(const clang::Expr *e, AggValueSlot aggSlot=AggValueSlot::ignored())
Emit code to compute the specified expression which can have any type.
mlir::LogicalResult emitSwitchStmt(const clang::SwitchStmt &s)
mlir::LogicalResult emitCaseStmt(const clang::CaseStmt &s, mlir::Type condType, bool buildingTopLevelCase)
LValue emitArraySubscriptExpr(const clang::ArraySubscriptExpr *e)
llvm::ScopedHashTableScope< const clang::Decl *, mlir::Value > SymTableScopeTy
OpenACCDataOperandInfo getOpenACCDataOperandInfo(const Expr *e)
AggValueSlot::Overlap_t getOverlapForFieldInit(const FieldDecl *fd)
mlir::LogicalResult emitSimpleStmt(const clang::Stmt *s, bool useCurrentScope)
mlir::Operation * curFn
The current function or global initializer that is generated code for.
mlir::LogicalResult emitAsmStmt(const clang::AsmStmt &s)
Definition CIRGenAsm.cpp:86
mlir::Value emitScalarConversion(mlir::Value src, clang::QualType srcType, clang::QualType dstType, clang::SourceLocation loc)
Emit a conversion from the specified type to the specified destination type, both of which are CIR sc...
mlir::Value emitPromotedComplexExpr(const Expr *e, QualType promotionType)
ImplicitParamDecl * cxxStructorImplicitParamDecl
When generating code for a constructor or destructor, this will hold the implicit argument (e....
mlir::LogicalResult emitOpenACCComputeConstruct(const OpenACCComputeConstruct &s)
EHScopeStack ehStack
Tracks function scope overall cleanup handling.
mlir::Value emitUnPromotedValue(mlir::Value result, QualType unPromotionType)
mlir::LogicalResult emitSwitchBody(const clang::Stmt *s)
mlir::LogicalResult emitForStmt(const clang::ForStmt &s)
AggValueSlot createAggTemp(QualType ty, mlir::Location loc, const Twine &name="tmp", Address *alloca=nullptr)
Create a temporary memory object for the given aggregate type.
std::optional< mlir::Value > fnRetAlloca
The compiler-generated variable that holds the return value.
void emitImplicitAssignmentOperatorBody(FunctionArgList &args)
clang::SanitizerSet sanOpts
Sanitizers enabled for this function.
mlir::Type convertTypeForMem(QualType t)
clang::QualType buildFunctionArgList(clang::GlobalDecl gd, FunctionArgList &args)
ConditionalInfo emitConditionalBlocks(const AbstractConditionalOperator *e, const FuncTy &branchGenFunc)
void emitCtorPrologue(const clang::CXXConstructorDecl *ctor, clang::CXXCtorType ctorType, FunctionArgList &args)
This routine generates necessary code to initialize base classes and non-static data members belongin...
mlir::Value emitAlloca(llvm::StringRef name, mlir::Type ty, mlir::Location loc, clang::CharUnits alignment, bool insertIntoFnEntryBlock, mlir::Value arraySize=nullptr)
void emitUnreachable(clang::SourceLocation loc, bool createNewBlock)
Emit a reached-unreachable diagnostic if loc is valid and runtime checking is enabled.
mlir::Value createDummyValue(mlir::Location loc, clang::QualType qt)
void emitCXXConstructExpr(const clang::CXXConstructExpr *e, AggValueSlot dest)
mlir::Value emitLoadOfComplex(LValue src, SourceLocation loc)
Load a complex number from the specified l-value.
LValue emitAggExprToLValue(const Expr *e)
clang::CurrentSourceLocExprScope curSourceLocExprScope
Source location information about the default argument or member initializer expression we're evaluat...
mlir::Value loadCXXVTT()
Load the VTT parameter to base constructors/destructors have virtual bases.
void emitVarDecl(const clang::VarDecl &d)
This method handles emission of any variable declaration inside a function, including static vars etc...
LValue emitCompoundAssignmentLValue(const clang::CompoundAssignOperator *e)
mlir::Value emitCXXNewExpr(const CXXNewExpr *e)
RValue getUndefRValue(clang::QualType ty)
Get an appropriate 'undef' rvalue for the given type.
Address returnValue
The temporary alloca to hold the return value.
LValue makeAddrLValue(Address addr, QualType ty, LValueBaseInfo baseInfo)
mlir::LogicalResult emitLabel(const clang::LabelDecl &d)
void emitCXXConstructorCall(const clang::CXXConstructorDecl *d, clang::CXXCtorType type, bool forVirtualBase, bool delegating, AggValueSlot thisAVS, const clang::CXXConstructExpr *e)
static bool hasAggregateEvaluationKind(clang::QualType type)
mlir::Value getVTablePtr(mlir::Location loc, Address thisAddr, const clang::CXXRecordDecl *vtableClass)
Return the Value of the vtable pointer member pointed to by thisAddr.
void emitArrayDestroy(mlir::Value begin, mlir::Value numElements, QualType elementType, CharUnits elementAlign, Destroyer *destroyer)
Destroys all the elements of the given array, beginning from last to first.
RValue emitAnyExprToTemp(const clang::Expr *e)
Similarly to emitAnyExpr(), however, the result will always be accessible even if no aggregate locati...
void finishFunction(SourceLocation endLoc)
mlir::LogicalResult emitOpenACCShutdownConstruct(const OpenACCShutdownConstruct &s)
mlir::LogicalResult emitFunctionBody(const clang::Stmt *body)
mlir::LogicalResult emitBreakStmt(const clang::BreakStmt &s)
mlir::Value emitComplexPrePostIncDec(const UnaryOperator *e, LValue lv, cir::UnaryOpKind op, bool isPre)
mlir::Value emitTernaryOnBoolExpr(const clang::Expr *cond, mlir::Location loc, const clang::Stmt *thenS, const clang::Stmt *elseS)
void emitStoreOfComplex(mlir::Location loc, mlir::Value v, LValue dest, bool isInit)
EmitStoreOfComplex - Store a complex number into the specified l-value.
llvm::SmallPtrSet< const clang::CXXRecordDecl *, 4 > VisitedVirtualBasesSetTy
void emitScalarInit(const clang::Expr *init, mlir::Location loc, LValue lvalue, bool capturedByInit=false)
LValue emitUnaryOpLValue(const clang::UnaryOperator *e)
void emitReturnOfRValue(mlir::Location loc, RValue rv, QualType ty)
bool shouldEmitVTableTypeCheckedLoad(const CXXRecordDecl *rd)
Returns whether we should perform a type checked load when loading a virtual function for virtual cal...
RValue emitLoadOfBitfieldLValue(LValue lv, SourceLocation loc)
RValue emitCall(const CIRGenFunctionInfo &funcInfo, const CIRGenCallee &callee, ReturnValueSlot returnValue, const CallArgList &args, cir::CIRCallOpInterface *callOp, mlir::Location loc)
LValue emitComplexAssignmentLValue(const BinaryOperator *e)
void emitCallArg(CallArgList &args, const clang::Expr *e, clang::QualType argType)
clang::FieldDecl * lambdaThisCaptureField
mlir::LogicalResult emitContinueStmt(const clang::ContinueStmt &s)
const clang::Decl * curCodeDecl
This is the inner-most code context, which includes blocks.
void emitConstructorBody(FunctionArgList &args)
LValue emitLValueForFieldInitialization(LValue base, const clang::FieldDecl *field, llvm::StringRef fieldName)
Like emitLValueForField, excpet that if the Field is a reference, this will return the address of the...
LValue emitCallExprLValue(const clang::CallExpr *e)
bool haveInsertPoint() const
True if an insertion point is defined.
llvm::SmallVector< mlir::Type, 2 > condTypeStack
The type of the condition for the emitting switch statement.
mlir::Value emitScalarExpr(const clang::Expr *e)
Emit the computation of the specified expression of scalar type.
void emitAutoVarInit(const AutoVarEmission &emission)
Emit the initializer for an allocated variable.
void emitInitializerForField(clang::FieldDecl *field, LValue lhs, clang::Expr *init)
void emitStopPoint(const Stmt *s)
Build a debug stoppoint if we are emitting debug info.
void maybeEmitDeferredVarDeclInit(const VarDecl *vd)
void emitVAEnd(mlir::Value vaList)
Emits the end of a CIR variable-argument operation (cir.va_start)
mlir::Value emitToMemory(mlir::Value value, clang::QualType ty)
Given a value and its clang type, returns the value casted to its memory representation.
mlir::LogicalResult emitOpenACCHostDataConstruct(const OpenACCHostDataConstruct &s)
LValue emitLValueForField(LValue base, const clang::FieldDecl *field)
mlir::LogicalResult emitIfStmt(const clang::IfStmt &s)
void emitAutoVarDecl(const clang::VarDecl &d)
Emit code and set up symbol table for a variable declaration with auto, register, or no storage class...
void pushDestroy(CleanupKind kind, Address addr, QualType type, Destroyer *destroyer)
mlir::Value emitPromotedScalarExpr(const Expr *e, QualType promotionType)
AggValueSlot::Overlap_t getOverlapForReturnValue()
Determine whether a return value slot may overlap some other object.
mlir::LogicalResult emitSwitchCase(const clang::SwitchCase &s, bool buildingTopLevelCase)
Address emitLoadOfReference(LValue refLVal, mlir::Location loc, LValueBaseInfo *pointeeBaseInfo)
Address getAddressOfDirectBaseInCompleteClass(mlir::Location loc, Address value, const CXXRecordDecl *derived, const CXXRecordDecl *base, bool baseIsVirtual)
Convert the given pointer to a complete class to the given direct base.
bool shouldNullCheckClassCastValue(const CastExpr *ce)
CIRGenBuilderTy & getBuilder()
void emitDecl(const clang::Decl &d, bool evaluateConditionDecl=false)
LValue emitBinaryOperatorLValue(const BinaryOperator *e)
mlir::Value emitOpenACCIntExpr(const Expr *intExpr)
Address getAddrOfBitFieldStorage(LValue base, const clang::FieldDecl *field, mlir::Type fieldType, unsigned index)
AggValueSlot::Overlap_t getOverlapForBaseInit(const CXXRecordDecl *rd, const CXXRecordDecl *baseRD, bool isVirtual)
Determine whether a base class initialization may overlap some other object.
void emitDestroy(Address addr, QualType type, Destroyer *destroyer)
Immediately perform the destruction of the given object.
const CIRGenModule & getCIRGenModule() const
void startFunction(clang::GlobalDecl gd, clang::QualType returnType, cir::FuncOp fn, cir::FuncType funcType, FunctionArgList args, clang::SourceLocation loc, clang::SourceLocation startLoc)
Emit code for the start of a function.
unsigned counterRefTmp
Hold counters for incrementally naming temporaries.
mlir::MLIRContext & getMLIRContext()
mlir::LogicalResult emitOpenACCEnterDataConstruct(const OpenACCEnterDataConstruct &s)
Destroyer * getDestroyer(clang::QualType::DestructionKind kind)
void Destroyer(CIRGenFunction &cgf, Address addr, QualType ty)
void emitDestructorBody(FunctionArgList &args)
Emits the body of the current destructor.
void emitAtomicInit(Expr *init, LValue dest)
LValue emitCastLValue(const CastExpr *e)
Casts are never lvalues unless that cast is to a reference type.
mlir::Value emitLoadOfScalar(LValue lvalue, SourceLocation loc)
EmitLoadOfScalar - Load a scalar value from an address, taking care to appropriately convert from the...
bool containsLabel(const clang::Stmt *s, bool ignoreCaseStmts=false)
Return true if the statement contains a label in it.
DeclMapTy localDeclMap
This keeps track of the CIR allocas or globals for local C declarations.
mlir::Value createOpenACCConstantInt(mlir::Location loc, unsigned width, int64_t value)
LValue emitDeclRefLValue(const clang::DeclRefExpr *e)
void emitComplexExprIntoLValue(const Expr *e, LValue dest, bool isInit)
llvm::DenseMap< const clang::ValueDecl *, clang::FieldDecl * > lambdaCaptureFields
ConstantEmission tryEmitAsConstant(const DeclRefExpr *refExpr)
Try to emit a reference to the given value without producing it as an l-value.
mlir::Value emitAlignmentAssumption(mlir::Value ptrValue, QualType ty, SourceLocation loc, SourceLocation assumptionLoc, int64_t alignment, mlir::Value offsetValue=nullptr)
mlir::LogicalResult emitCaseDefaultCascade(const T *stmt, mlir::Type condType, mlir::ArrayAttr value, cir::CaseOpKind kind, bool buildingTopLevelCase)
void emitCXXThrowExpr(const CXXThrowExpr *e)
LValue makeAddrLValue(Address addr, QualType ty, AlignmentSource source=AlignmentSource::Type)
void emitCXXDestructorCall(const CXXDestructorDecl *dd, CXXDtorType type, bool forVirtualBase, bool delegating, Address thisAddr, QualType thisTy)
llvm::SmallVector< VPtr, 4 > VPtrsVector
void emitLambdaStaticInvokeBody(const CXXMethodDecl *md)
bool sawAsmBlock
Whether or not a Microsoft-style asm block has been processed within this fuction.
mlir::LogicalResult emitDeclStmt(const clang::DeclStmt &s)
llvm::DenseMap< const OpaqueValueExpr *, RValue > opaqueRValues
mlir::LogicalResult emitDefaultStmt(const clang::DefaultStmt &s, mlir::Type condType, bool buildingTopLevelCase)
mlir::LogicalResult emitWhileStmt(const clang::WhileStmt &s)
mlir::LogicalResult emitLabelStmt(const clang::LabelStmt &s)
Address emitArrayToPointerDecay(const Expr *e, LValueBaseInfo *baseInfo=nullptr)
EHScopeStack::stable_iterator currentCleanupStackDepth
void emitCXXAggrConstructorCall(const CXXConstructorDecl *ctor, const clang::ArrayType *arrayType, Address arrayBegin, const CXXConstructExpr *e, bool newPointerIsChecked, bool zeroInitialize=false)
Emit a loop to call a particular constructor for each of several members of an array.
void pushFullExprCleanup(CleanupKind kind, As... a)
Push a cleanup to be run at the end of the current full-expression.
void emitDelegateCallArg(CallArgList &args, const clang::VarDecl *param, clang::SourceLocation loc)
We are performing a delegate call; that is, the current function is delegating to another one.
mlir::Value emitStoreThroughBitfieldLValue(RValue src, LValue dstresult)
llvm::DenseMap< const OpaqueValueExpr *, LValue > opaqueLValues
Keeps track of the current set of opaque value expressions.
CIRGenFunction(CIRGenModule &cgm, CIRGenBuilderTy &builder, bool suppressNewContext=false)
std::optional< mlir::Location > currSrcLoc
Use to track source locations across nested visitor traversals.
LValue emitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *e)
clang::ASTContext & getContext() const
RValue emitCXXMemberOrOperatorMemberCallExpr(const clang::CallExpr *ce, const clang::CXXMethodDecl *md, ReturnValueSlot returnValue, bool hasQualifier, clang::NestedNameSpecifier qualifier, bool isArrow, const clang::Expr *base)
void setAddrOfLocalVar(const clang::VarDecl *vd, Address addr)
Set the address of a local variable.
mlir::Value emitScalarConstant(const ConstantEmission &constant, Expr *e)
RValue emitBuiltinExpr(const clang::GlobalDecl &gd, unsigned builtinID, const clang::CallExpr *e, ReturnValueSlot returnValue)
void emitAggregateCopy(LValue dest, LValue src, QualType eltTy, AggValueSlot::Overlap_t mayOverlap)
Emit an aggregate copy.
void emitCXXDeleteExpr(const CXXDeleteExpr *e)
RValue emitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *e, const CXXMethodDecl *md, ReturnValueSlot returnValue)
mlir::LogicalResult emitCompoundStmt(const clang::CompoundStmt &s, Address *lastValue=nullptr, AggValueSlot slot=AggValueSlot::ignored())
void emitNullabilityCheck(LValue lhs, mlir::Value rhs, clang::SourceLocation loc)
Given an assignment *lhs = rhs, emit a test that checks if rhs is nonnull, if 1LHS is marked _Nonnull...
mlir::LogicalResult emitGotoStmt(const clang::GotoStmt &s)
void emitStoreThroughLValue(RValue src, LValue dst, bool isInit=false)
Store the specified rvalue into the specified lvalue, where both are guaranteed to the have the same ...
bool isLValueSuitableForInlineAtomic(LValue lv)
An LValue is a candidate for having its loads and stores be made atomic if we are operating under /vo...
mlir::LogicalResult emitStmt(const clang::Stmt *s, bool useCurrentScope, llvm::ArrayRef< const Attr * > attrs={})
void popCleanupBlocks(EHScopeStack::stable_iterator oldCleanupStackDepth)
Takes the old cleanup stack size and emits the cleanup blocks that have been added.
RValue getOrCreateOpaqueRValueMapping(const OpaqueValueExpr *e)
Given an opaque value expression, return its RValue mapping if it exists, otherwise create one.
Address createTempAllocaWithoutCast(mlir::Type ty, CharUnits align, mlir::Location loc, const Twine &name="tmp", mlir::Value arraySize=nullptr, mlir::OpBuilder::InsertPoint ip={})
This creates a alloca and inserts it into the entry block of the current region.
Address emitVAListRef(const Expr *e)
Build a "reference" to a va_list; this is either the address or the value of the expression,...
mlir::LogicalResult emitCompoundStmtWithoutScope(const clang::CompoundStmt &s, Address *lastValue=nullptr, AggValueSlot slot=AggValueSlot::ignored())
mlir::LogicalResult emitOpenACCExitDataConstruct(const OpenACCExitDataConstruct &s)
void emitIgnoredExpr(const clang::Expr *e)
Emit code to compute the specified expression, ignoring the result.
Address createMemTemp(QualType t, mlir::Location loc, const Twine &name="tmp", Address *alloca=nullptr, mlir::OpBuilder::InsertPoint ip={})
Create a temporary memory object of the given type, with appropriate alignmen and cast it to the defa...
void emitDelegatingCXXConstructorCall(const CXXConstructorDecl *ctor, const FunctionArgList &args)
void emitAggExpr(const clang::Expr *e, AggValueSlot slot)
mlir::Value emitAlloca(llvm::StringRef name, mlir::Type ty, mlir::Location loc, clang::CharUnits alignment, mlir::OpBuilder::InsertPoint ip, mlir::Value arraySize=nullptr)
mlir::LogicalResult emitOpenACCAtomicConstruct(const OpenACCAtomicConstruct &s)
void popCleanupBlock()
Pops a cleanup block.
mlir::Value emitVAArg(VAArgExpr *ve)
Generate code to get an argument from the passed in pointer and update it accordingly.
RValue emitCXXPseudoDestructorExpr(const CXXPseudoDestructorExpr *expr)
LValue emitCompoundLiteralLValue(const CompoundLiteralExpr *e)
void emitAutoVarCleanups(const AutoVarEmission &emission)
RValue emitRotate(const CallExpr *e, bool isRotateLeft)
mlir::LogicalResult emitOpenACCLoopConstruct(const OpenACCLoopConstruct &s)
CIRGenCallee emitCallee(const clang::Expr *e)
Address emitAddrOfFieldStorage(Address base, const FieldDecl *field, llvm::StringRef fieldName, unsigned fieldIndex)
Get the address of a zero-sized field within a record.
This class organizes the cross-function state that is used while generating CIR code.
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
This class organizes the cross-module state that is used while lowering AST types to CIR types.
Definition CIRGenTypes.h:48
A saved depth on the scope stack.
A stack of scopes which respond to exceptions, including cleanups and catch blocks.
Type for representing both the decl and type of parameters to a function.
Definition CIRGenCall.h:191
static LValue makeAddr(Address address, clang::QualType t, LValueBaseInfo baseInfo)
This trivial value class is used to represent the result of an expression that is evaluated.
Definition CIRGenValue.h:33
Contains the address where the return value of a function can be stored, and whether the address is v...
Definition CIRGenCall.h:252
Represents a call to a C++ constructor.
Definition ExprCXX.h:1549
Represents a C++ constructor within a class.
Definition DeclCXX.h:2604
Represents a C++ base or member initializer.
Definition DeclCXX.h:2369
A use of a default initializer in a constructor or in aggregate initialization.
Definition ExprCXX.h:1378
Represents a delete expression for memory deallocation and destructor calls, e.g.
Definition ExprCXX.h:2628
Represents a C++ destructor within a class.
Definition DeclCXX.h:2869
CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for statement, represented as 'for (ra...
Definition StmtCXX.h:135
Represents a call to a member function that may be written either with member call syntax (e....
Definition ExprCXX.h:179
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2129
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)".
Definition ExprCXX.h:2357
A call to an overloaded operator written using operator syntax.
Definition ExprCXX.h:84
Represents a C++ pseudo-destructor (C++ [expr.pseudo]).
Definition ExprCXX.h:2747
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
A C++ throw-expression (C++ [except.throw]).
Definition ExprCXX.h:1209
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2877
CaseStmt - Represent a case statement.
Definition Stmt.h:1920
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Definition Expr.h:3610
CharUnits - This is an opaque type for sizes expressed in character units.
Definition CharUnits.h:38
bool isZero() const
isZero - Test whether the quantity equals zero.
Definition CharUnits.h:122
llvm::Align getAsAlign() const
getAsAlign - Returns Quantity as a valid llvm::Align, Beware llvm::Align assumes power of two 8-bit b...
Definition CharUnits.h:189
CompoundAssignOperator - For compound assignments (e.g.
Definition Expr.h:4234
CompoundLiteralExpr - [C99 6.5.2.5].
Definition Expr.h:3539
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition Stmt.h:1720
ContinueStmt - This represents a continue.
Definition Stmt.h:3119
Represents the current source location and context used to determine the value of the source location...
A reference to a declared variable, function, enum, etc.
Definition Expr.h:1270
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition Stmt.h:1611
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
DoStmt - This represents a 'do/while' stmt.
Definition Stmt.h:2832
This represents one expression.
Definition Expr.h:112
Represents a member of a struct/union/class.
Definition Decl.h:3160
ForStmt - This represents a 'for (init;cond;inc)' stmt.
Definition Stmt.h:2888
Represents a function declaration or definition.
Definition Decl.h:2000
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5266
GlobalDecl - represents a global declaration.
Definition GlobalDecl.h:57
GotoStmt - This represents a direct goto.
Definition Stmt.h:2969
IfStmt - This represents an if/then/else.
Definition Stmt.h:2259
Represents the declaration of a label.
Definition Decl.h:524
LabelStmt - Represents a label, which has a substatement.
Definition Stmt.h:2146
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Represents a prvalue temporary that is written into memory so that a reference can bind to it.
Definition ExprCXX.h:4922
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition Expr.h:3298
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
ObjCMethodDecl - Represents an instance or class method declaration.
Definition DeclObjC.h:140
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Definition Expr.h:1178
Expr * getSourceExpr() const
The source expression of an opaque value expression is the expression which originally generated the ...
Definition Expr.h:1228
Represents a parameter to a function.
Definition Decl.h:1790
A (possibly-)qualified type.
Definition TypeBase.h:937
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition TypeBase.h:8327
The collection of all-type qualifiers we support.
Definition TypeBase.h:331
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
Definition Stmt.h:3160
Encodes a location in the source.
A trivial tuple used to represent a source range.
Stmt - This represents one statement.
Definition Stmt.h:85
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:334
StringLiteral - This represents a string literal expression, e.g.
Definition Expr.h:1799
SwitchStmt - This represents a 'switch' stmt.
Definition Stmt.h:2509
Exposes information about the current target.
Definition TargetInfo.h:226
Represents a declaration of a type.
Definition Decl.h:3513
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition Expr.h:2244
Represents a call to the builtin function __builtin_va_arg.
Definition Expr.h:4891
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition Decl.h:712
Represents a variable declaration or definition.
Definition Decl.h:926
WhileStmt - This represents a 'while' stmt.
Definition Stmt.h:2697
#define bool
Definition gpuintrin.h:32
AlignmentSource
The source of the alignment of an l-value; an expression of confidence in the alignment actually matc...
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const AstTypeMatcher< ArrayType > arrayType
const internal::VariadicAllOfMatcher< Stmt > stmt
Matches statements.
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
CXXCtorType
C++ constructor types.
Definition ABI.h:24
OpenACCDirectiveKind
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
OpenACCComputeConstruct(OpenACCDirectiveKind K, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses, Stmt *StructuredBlock)
const FunctionProtoType * T
CXXDtorType
C++ destructor types.
Definition ABI.h:34
#define true
Definition stdbool.h:25
static bool aggValueSlot()
static bool peepholeProtection()
static bool opAllocaEscapeByReference()
static bool generateDebugInfo()
AutoVarEmission(const clang::VarDecl &variable)
bool IsEscapingByRef
True if the variable is a __block variable that is captured by an escaping block.
Address getAllocatedAddress() const
Returns the raw, allocated address, which is not necessarily the address of the object itself.
Address getObjectAddress(CIRGenFunction &cgf) const
Returns the address of the object within this declaration.
bool EmittedAsOffload
True if the variable was emitted as an offload recipe, and thus doesn't have the same sort of alloca ...
Address Addr
The address of the alloca for languages with explicit address space (e.g.
bool IsConstantAggregate
True if the variable is of aggregate type and has a constant initializer.
Represents a scope, including function bodies, compound statements, and the substatements of if/while...
mlir::Block * createCleanupBlock(mlir::OpBuilder &builder)
mlir::Block * getOrCreateRetBlock(CIRGenFunction &cgf, mlir::Location loc)
LexicalScope(CIRGenFunction &cgf, mlir::Location loc, mlir::Block *eb)
void updateRetLoc(mlir::Block *b, mlir::Location loc)
mlir::Block * getCleanupBlock(mlir::OpBuilder &builder)
mlir::Block * getOrCreateCleanupBlock(mlir::OpBuilder &builder)
mlir::Location getRetLoc(mlir::Block *b)
llvm::PointerUnion< const clang::FunctionProtoType *, const clang::ObjCMethodDecl * > p
PrototypeWrapper(const clang::ObjCMethodDecl *md)
PrototypeWrapper(const clang::FunctionProtoType *ft)
const clang::CXXRecordDecl * vtableClass
const clang::CXXRecordDecl * nearestVBase