clang 24.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"
38#include "llvm/ADT/ScopedHashTable.h"
39#include "llvm/IR/Instructions.h"
40
41namespace {
42class ScalarExprEmitter;
43} // namespace
44
45namespace mlir {
46namespace acc {
47class LoopOp;
48} // namespace acc
49} // namespace mlir
50
51namespace clang::CIRGen {
52
53struct CGCoroData;
54
56public:
58
59private:
60 friend class ::ScalarExprEmitter;
61 /// The builder is a helper class to create IR inside a function. The
62 /// builder is stateful, in particular it keeps an "insertion point": this
63 /// is where the next operations will be introduced.
64 CIRGenBuilderTy &builder;
65
66public:
67 /// The GlobalDecl for the current function being compiled or the global
68 /// variable currently being initialized.
70
72
73 /// The compiler-generated variable that holds the return value.
74 std::optional<mlir::Value> fnRetAlloca;
75
76 // Holds coroutine data if the current function is a coroutine. We use a
77 // wrapper to manage its lifetime, so that we don't have to define CGCoroData
78 // in this header.
79 struct CGCoroInfo {
80 std::unique_ptr<CGCoroData> data;
81 CGCoroInfo();
83 };
85
86 bool isCoroutine() const { return curCoro.data != nullptr; }
87
88 /// The temporary alloca to hold the return value. This is
89 /// invalid iff the function has no return value.
91
92 /// Tracks function scope overall cleanup handling.
94
95 typedef void Destroyer(CIRGenFunction &cgf, Address addr, QualType ty);
96
97 /// A cleanup entry that will be promoted onto the EH scope stack at a later
98 /// point. Used by both the lifetime-extended cleanup stack (promoted when
99 /// the enclosing scope exits) and the deferred conditional cleanup stack
100 /// (promoted at the enclosing full-expression level).
101 ///
102 /// Currently only DestroyObject cleanups use this. When other cleanup types
103 /// are needed (e.g., CallLifetimeEnd), this struct can be extended with a
104 /// std::variant of cleanup data types.
112
114
116
117 /// A cleanup that was pushed to the EH stack but whose deactivation is
118 /// deferred until the enclosing CleanupDeactivationScope exits. Used to
119 /// protect partially-constructed aggregates (e.g. lambda captures) so that
120 /// already-initialized sub-objects are destroyed if a later initializer
121 /// throws, while avoiding double-destruction after full construction.
127
128 /// Scope that deactivates all enclosed deferred cleanups on exit.
129 /// Mirrors CodeGenFunction::CleanupDeactivationScope in classic codegen.
133 bool deactivated = false;
134
138
140 assert(!deactivated && "Deactivating already deactivated scope");
141 auto &stack = cgf.deferredDeactivationCleanupStack;
142 for (size_t i = stack.size(); i > oldDeactivateCleanupStackSize; i--) {
143 cgf.deactivateCleanupBlock(stack[i - 1].cleanup,
144 stack[i - 1].dominatingIP);
145 stack[i - 1].dominatingIP->erase();
146 }
147 stack.resize(oldDeactivateCleanupStackSize);
148 deactivated = true;
149 }
150
155 };
156
158
159 /// If a ParmVarDecl had the pass_object_size attribute, this will contain a
160 /// mapping from said ParmVarDecl to its implicit "object_size" parameter.
161 llvm::SmallDenseMap<const ParmVarDecl *, const ImplicitParamDecl *>
163
164 /// A mapping from NRVO variables to the flags used to indicate
165 /// when the NRVO has been applied to this variable.
166 llvm::DenseMap<const VarDecl *, mlir::Value> nrvoFlags;
167
168 llvm::DenseMap<const clang::ValueDecl *, clang::FieldDecl *>
171
172 /// CXXThisDecl - When generating code for a C++ member function,
173 /// this will hold the implicit 'this' declaration.
175 mlir::Value cxxabiThisValue = nullptr;
176 mlir::Value cxxThisValue = nullptr;
179
180 /// When generating code for a constructor or destructor, this will hold the
181 /// implicit argument (e.g. VTT).
184
185 /// The value of 'this' to sue when evaluating CXXDefaultInitExprs within this
186 /// expression.
188
189 /// The values of function arguments to use when evaluating
190 /// CXXInheritedCtorInitExprs within this context.
192
193 /// The current array initialization index when evaluating an
194 /// ArrayInitIndexExpr within an ArrayInitLoopExpr.
195 mlir::Value arrayInitIndex = nullptr;
196
197 // Holds the Decl for the current outermost non-closure context
198 const clang::Decl *curFuncDecl = nullptr;
199 /// This is the inner-most code context, which includes blocks.
200 const clang::Decl *curCodeDecl = nullptr;
203
204 /// The current function or global initializer that is generated code for.
205 /// This is usually a cir::FuncOp, but it can also be a cir::GlobalOp for
206 /// global initializers.
207 mlir::Operation *curFn = nullptr;
208
209 /// Save Parameter Decl for coroutine.
211
212 using DeclMapTy = llvm::DenseMap<const clang::Decl *, Address>;
213 /// This keeps track of the CIR allocas or globals for local C
214 /// declarations.
216
217 /// The type of the condition for the emitting switch statement.
219
220 clang::ASTContext &getContext() const { return cgm.getASTContext(); }
221
222 CIRGenBuilderTy &getBuilder() { return builder; }
223
225 const CIRGenModule &getCIRGenModule() const { return cgm; }
226
228 // We currently assume this isn't called for a global initializer.
229 auto fn = mlir::cast<cir::FuncOp>(curFn);
230 return &fn.getRegion().front();
231 }
232
233 /// Sanitizers enabled for this function.
235
237 public:
241
242 private:
243 void ConstructorHelper(clang::FPOptions FPFeatures);
244 CIRGenFunction &cgf;
245 clang::FPOptions oldFPFeatures;
246 llvm::fp::ExceptionBehavior oldExcept;
247 llvm::RoundingMode oldRounding;
248 };
250
251 /// The symbol table maps a variable name to a value in the current scope.
252 /// Entering a function creates a new scope, and the function arguments are
253 /// added to the mapping. When the processing of a function is terminated,
254 /// the scope is destroyed and the mappings created in this scope are
255 /// dropped.
256 using SymTableTy = llvm::ScopedHashTable<const clang::Decl *, mlir::Value>;
258
259 /// Whether a cir.stacksave operation has been added. Used to avoid
260 /// inserting cir.stacksave for multiple VLAs in the same scope.
261 bool didCallStackSave = false;
262
263 /// Whether or not a Microsoft-style asm block has been processed within
264 /// this fuction. These can potentially set the return value.
265 bool sawAsmBlock = false;
266
267 /// In C++, whether we are code generating a thunk. This controls whether we
268 /// should emit cleanups.
269 bool curFuncIsThunk = false;
270
271 mlir::Type convertTypeForMem(QualType t);
272
273 mlir::Type convertType(clang::QualType t);
274 mlir::Type convertType(const TypeDecl *t) {
275 return convertType(getContext().getTypeDeclType(t));
276 }
277
278 /// Get integer from a mlir::Value that is an int constant or a constant op.
279 static int64_t getSExtIntValueFromConstOp(mlir::Value val) {
280 auto constOp = val.getDefiningOp<cir::ConstantOp>();
281 assert(constOp && "getSExtIntValueFromConstOp call with non ConstantOp");
282 return constOp.getIntValue().getSExtValue();
283 }
284
285 /// Get zero-extended integer from a mlir::Value that is an int constant or a
286 /// constant op.
287 static int64_t getZExtIntValueFromConstOp(mlir::Value val) {
288 auto constOp = val.getDefiningOp<cir::ConstantOp>();
289 assert(constOp && "getZExtIntValueFromConstOp call with non ConstantOp");
290 return constOp.getIntValue().getZExtValue();
291 }
292
293 /// Return the cir::TypeEvaluationKind of QualType \c type.
295
299
303
305 bool suppressNewContext = false);
307
308 CIRGenTypes &getTypes() const { return cgm.getTypes(); }
309
310 const TargetInfo &getTarget() const { return cgm.getTarget(); }
311 mlir::MLIRContext &getMLIRContext() { return cgm.getMLIRContext(); }
312
314 return cgm.getTargetCIRGenInfo();
315 }
316
317 // ---------------------
318 // Opaque value handling
319 // ---------------------
320
321 /// Keeps track of the current set of opaque value expressions.
322 llvm::DenseMap<const OpaqueValueExpr *, LValue> opaqueLValues;
323 llvm::DenseMap<const OpaqueValueExpr *, RValue> opaqueRValues;
324
325 // This keeps track of the associated size for each VLA type.
326 // We track this by the size expression rather than the type itself because
327 // in certain situations, like a const qualifier applied to an VLA typedef,
328 // multiple VLA types can share the same size expression.
329 // FIXME: Maybe this could be a stack of maps that is pushed/popped as we
330 // enter/leave scopes.
331 llvm::DenseMap<const Expr *, mlir::Value> vlaSizeMap;
332
333public:
334 /// A non-RAII class containing all the information about a bound
335 /// opaque value. OpaqueValueMapping, below, is a RAII wrapper for
336 /// this which makes individual mappings very simple; using this
337 /// class directly is useful when you have a variable number of
338 /// opaque values or don't want the RAII functionality for some
339 /// reason.
340 class OpaqueValueMappingData {
341 const OpaqueValueExpr *opaqueValue;
342 bool boundLValue;
343
344 OpaqueValueMappingData(const OpaqueValueExpr *ov, bool boundLValue)
345 : opaqueValue(ov), boundLValue(boundLValue) {}
346
347 public:
348 OpaqueValueMappingData() : opaqueValue(nullptr) {}
349
350 static bool shouldBindAsLValue(const Expr *expr) {
351 // gl-values should be bound as l-values for obvious reasons.
352 // Records should be bound as l-values because IR generation
353 // always keeps them in memory. Expressions of function type
354 // act exactly like l-values but are formally required to be
355 // r-values in C.
356 return expr->isGLValue() || expr->getType()->isFunctionType() ||
358 }
359
361 bind(CIRGenFunction &cgf, const OpaqueValueExpr *ov, const Expr *e) {
362 if (shouldBindAsLValue(ov))
363 return bind(cgf, ov, cgf.emitLValue(e));
364 return bind(cgf, ov, cgf.emitAnyExpr(e));
365 }
366
368 bind(CIRGenFunction &cgf, const OpaqueValueExpr *ov, const LValue &lv) {
369 assert(shouldBindAsLValue(ov));
370 cgf.opaqueLValues.insert(std::make_pair(ov, lv));
371 return OpaqueValueMappingData(ov, true);
372 }
373
375 bind(CIRGenFunction &cgf, const OpaqueValueExpr *ov, const RValue &rv) {
376 assert(!shouldBindAsLValue(ov));
377 cgf.opaqueRValues.insert(std::make_pair(ov, rv));
378
379 OpaqueValueMappingData data(ov, false);
380
381 // Work around an extremely aggressive peephole optimization in
382 // EmitScalarConversion which assumes that all other uses of a
383 // value are extant.
385 return data;
386 }
387
388 bool isValid() const { return opaqueValue != nullptr; }
389 void clear() { opaqueValue = nullptr; }
390
392 assert(opaqueValue && "no data to unbind!");
393
394 if (boundLValue) {
395 cgf.opaqueLValues.erase(opaqueValue);
396 } else {
397 cgf.opaqueRValues.erase(opaqueValue);
399 }
400 }
401 };
402
403 /// An RAII object to set (and then clear) a mapping for an OpaqueValueExpr.
405 CIRGenFunction &cgf;
407
408 public:
412
413 /// Build the opaque value mapping for the given conditional
414 /// operator if it's the GNU ?: extension. This is a common
415 /// enough pattern that the convenience operator is really
416 /// helpful.
417 ///
420 : cgf(cgf) {
421 if (mlir::isa<ConditionalOperator>(op))
422 // Leave Data empty.
423 return;
424
426 mlir::cast<BinaryConditionalOperator>(op);
428 e->getCommon());
429 }
430
431 /// Build the opaque value mapping for an OpaqueValueExpr whose source
432 /// expression is set to the expression the OVE represents.
434 : cgf(cgf) {
435 if (ov) {
436 assert(ov->getSourceExpr() && "wrong form of OpaqueValueMapping used "
437 "for OVE with no source expression");
438 data = OpaqueValueMappingData::bind(cgf, ov, ov->getSourceExpr());
439 }
440 }
441
443 LValue lvalue)
444 : cgf(cgf),
445 data(OpaqueValueMappingData::bind(cgf, opaqueValue, lvalue)) {}
446
448 RValue rvalue)
449 : cgf(cgf),
450 data(OpaqueValueMappingData::bind(cgf, opaqueValue, rvalue)) {}
451
452 void pop() {
453 data.unbind(cgf);
454 data.clear();
455 }
456
458 if (data.isValid())
459 data.unbind(cgf);
460 }
461 };
462
463private:
464 /// Declare a variable in the current scope, return success if the variable
465 /// wasn't declared yet.
466 void declare(mlir::Value addrVal, const clang::Decl *var, clang::QualType ty,
467 mlir::Location loc, clang::CharUnits alignment,
468 bool isParam = false);
469
470public:
471 mlir::Value createDummyValue(mlir::Location loc, clang::QualType qt);
472
473 void emitNullInitialization(mlir::Location loc, Address destPtr, QualType ty);
474
475private:
476 // Track current variable initialization (if there's one)
477 const clang::VarDecl *currVarDecl = nullptr;
478 class VarDeclContext {
480 const clang::VarDecl *oldVal = nullptr;
481
482 public:
483 VarDeclContext(CIRGenFunction &p, const VarDecl *value) : p(p) {
484 if (p.currVarDecl)
485 oldVal = p.currVarDecl;
486 p.currVarDecl = value;
487 }
488
489 /// Can be used to restore the state early, before the dtor
490 /// is run.
491 void restore() { p.currVarDecl = oldVal; }
492 ~VarDeclContext() { restore(); }
493 };
494
495public:
496 /// Use to track source locations across nested visitor traversals.
497 /// Always use a `SourceLocRAIIObject` to change currSrcLoc.
498 std::optional<mlir::Location> currSrcLoc;
500 CIRGenFunction &cgf;
501 std::optional<mlir::Location> oldLoc;
502
503 public:
504 SourceLocRAIIObject(CIRGenFunction &cgf, mlir::Location value) : cgf(cgf) {
505 if (cgf.currSrcLoc)
506 oldLoc = cgf.currSrcLoc;
507 cgf.currSrcLoc = value;
508 }
509
510 /// Can be used to restore the state early, before the dtor
511 /// is run.
512 void restore() { cgf.currSrcLoc = oldLoc; }
514 };
515
517 llvm::ScopedHashTableScope<const clang::Decl *, mlir::Value>;
518
519 /// Hold counters for incrementally naming temporaries
520 unsigned counterRefTmp = 0;
521 unsigned counterAggTmp = 0;
522 std::string getCounterRefTmpAsString();
523 std::string getCounterAggTmpAsString();
524
525 /// Helpers to convert Clang's SourceLocation to a MLIR Location.
526 mlir::Location getLoc(clang::SourceLocation srcLoc);
527 mlir::Location getLoc(clang::SourceRange srcLoc);
528 mlir::Location getLoc(mlir::Location lhs, mlir::Location rhs);
529
530 const clang::LangOptions &getLangOpts() const { return cgm.getLangOpts(); }
531
532 /// True if an insertion point is defined. If not, this indicates that the
533 /// current code being emitted is unreachable.
534 /// FIXME(cir): we need to inspect this and perhaps use a cleaner mechanism
535 /// since we don't yet force null insertion point to designate behavior (like
536 /// LLVM's codegen does) and we probably shouldn't.
537 bool haveInsertPoint() const {
538 return builder.getInsertionBlock() != nullptr;
539 }
540
541 // Wrapper for function prototype sources. Wraps either a FunctionProtoType or
542 // an ObjCMethodDecl.
544 llvm::PointerUnion<const clang::FunctionProtoType *,
545 const clang::ObjCMethodDecl *>
547
550 };
551
553
556 RValue emitAtomicLoad(LValue lvalue, SourceLocation loc, cir::MemOrder order,
557 bool isVolatile = false,
559
560 /// An abstract representation of regular/ObjC call/message targets.
562 /// The function declaration of the callee.
563 [[maybe_unused]] const clang::Decl *calleeDecl;
564
565 public:
566 AbstractCallee() : calleeDecl(nullptr) {}
567 AbstractCallee(const clang::FunctionDecl *fd) : calleeDecl(fd) {}
568
569 bool hasFunctionDecl() const {
570 return llvm::isa_and_nonnull<clang::FunctionDecl>(calleeDecl);
571 }
572
573 const clang::Decl *getDecl() const { return calleeDecl; }
574
575 unsigned getNumParams() const {
576 if (const auto *fd = llvm::dyn_cast<clang::FunctionDecl>(calleeDecl))
577 return fd->getNumParams();
578 return llvm::cast<clang::ObjCMethodDecl>(calleeDecl)->param_size();
579 }
580
581 const clang::ParmVarDecl *getParamDecl(unsigned I) const {
582 if (const auto *fd = llvm::dyn_cast<clang::FunctionDecl>(calleeDecl))
583 return fd->getParamDecl(I);
584 return *(llvm::cast<clang::ObjCMethodDecl>(calleeDecl)->param_begin() +
585 I);
586 }
587 };
588
589 struct VlaSizePair {
590 mlir::Value numElts;
592
593 VlaSizePair(mlir::Value num, QualType ty) : numElts(num), type(ty) {}
594 };
595
596 /// Return the number of elements for a single dimension
597 /// for the given array type.
598 VlaSizePair getVLAElements1D(const VariableArrayType *vla);
599
600 /// Returns an MLIR::Value+QualType pair that corresponds to the size,
601 /// in non-variably-sized elements, of a variable length array type,
602 /// plus that largest non-variably-sized element type. Assumes that
603 /// the type has already been emitted with emitVariablyModifiedType.
604 VlaSizePair getVLASize(const VariableArrayType *type);
605 VlaSizePair getVLASize(QualType type);
606
608
609 mlir::Value getAsNaturalPointerTo(Address addr, QualType pointeeType) {
610 return getAsNaturalAddressOf(addr, pointeeType).getBasePointer();
611 }
612
613 void finishFunction(SourceLocation endLoc);
614
615 /// Determine whether the given initializer is trivial in the sense
616 /// that it requires no code to be generated.
617 bool isTrivialInitializer(const Expr *init);
618
619 /// If the specified expression does not fold to a constant, or if it does but
620 /// contains a label, return false. If it constant folds return true and set
621 /// the boolean result in Result.
622 bool constantFoldsToBool(const clang::Expr *cond, bool &resultBool,
623 bool allowLabels = false);
625 llvm::APSInt &resultInt,
626 bool allowLabels = false);
627
628 /// Return true if the statement contains a label in it. If
629 /// this statement is not executed normally, it not containing a label means
630 /// that we can just remove the code.
631 bool containsLabel(const clang::Stmt *s, bool ignoreCaseStmts = false);
632
633 Address emitExtVectorElementLValue(LValue lv, mlir::Location loc);
634
635 class ConstantEmission {
636 // Cannot use mlir::TypedAttr directly here because of bit availability.
637 llvm::PointerIntPair<mlir::Attribute, 1, bool> valueAndIsReference;
638 ConstantEmission(mlir::TypedAttr c, bool isReference)
639 : valueAndIsReference(c, isReference) {}
640
641 public:
643 static ConstantEmission forReference(mlir::TypedAttr c) {
644 return ConstantEmission(c, true);
645 }
646 static ConstantEmission forValue(mlir::TypedAttr c) {
647 return ConstantEmission(c, false);
648 }
649
650 explicit operator bool() const {
651 return valueAndIsReference.getOpaqueValue() != nullptr;
652 }
653
654 bool isReference() const { return valueAndIsReference.getInt(); }
656 assert(isReference());
657 cgf.cgm.errorNYI(refExpr->getSourceRange(),
658 "ConstantEmission::getReferenceLValue");
659 return {};
660 }
661
662 mlir::TypedAttr getValue() const {
663 assert(!isReference());
664 return mlir::cast<mlir::TypedAttr>(valueAndIsReference.getPointer());
665 }
666 };
667
668 ConstantEmission tryEmitAsConstant(const DeclRefExpr *refExpr);
669 ConstantEmission tryEmitAsConstant(const MemberExpr *me);
670
673 /// The address of the alloca for languages with explicit address space
674 /// (e.g. OpenCL) or alloca casted to generic pointer for address space
675 /// agnostic languages (e.g. C++). Invalid if the variable was emitted
676 /// as a global constant.
678
679 /// True if the variable is of aggregate type and has a constant
680 /// initializer.
682
683 /// True if the variable is a __block variable that is captured by an
684 /// escaping block.
685 bool isEscapingByRef = false;
686
687 /// True if the variable was emitted as an offload recipe, and thus doesn't
688 /// have the same sort of alloca initialization.
689 bool emittedAsOffload = false;
690
691 mlir::Value nrvoFlag{};
692
693 struct Invalid {};
695
698
700
701 bool wasEmittedAsGlobal() const { return !addr.isValid(); }
702
704
705 /// Returns the raw, allocated address, which is not necessarily
706 /// the address of the object itself. It is casted to default
707 /// address space for address space agnostic languages.
708 Address getAllocatedAddress() const { return addr; }
709
710 // Changes the stored address for the emission. This function should only
711 // be used in extreme cases, and isn't required to model normal AST
712 // initialization/variables.
714
715 /// Returns the address of the object within this declaration.
716 /// Note that this does not chase the forwarding pointer for
717 /// __block decls.
719 if (!isEscapingByRef)
720 return addr;
721
723 return Address::invalid();
724 }
725 };
726
727 /// IndirectBranch - The first time an indirect goto is seen we create a block
728 /// reserved for the indirect branch. The actual `cir.indirect_br` is emitted
729 /// at the end of the function, once every label destination is known.
730 mlir::Block *indirectGotoBlock = nullptr;
731
732 /// Labels whose address is taken in this function (via `&&label`, as either
733 /// an operation or a constant initializer). The indirect branch block is
734 /// created lazily on the first `goto *expr`; these targets are resolved to
735 /// their LabelOps and wired as `cir.indirect_br` successors in
736 /// finishIndirectBranch.
738
740
741 /// Perform the usual unary conversions on the specified expression and
742 /// compare the result against zero, returning an Int1Ty value.
743 mlir::Value evaluateExprAsBool(const clang::Expr *e);
744
745 cir::GlobalOp addInitializerToStaticVarDecl(const VarDecl &d,
746 cir::GlobalOp gv,
747 cir::GetGlobalOp gvAddr);
748
749 /// Enter the cleanups necessary to complete the given phase of destruction
750 /// for a destructor. The end result should call destructors on members and
751 /// base classes in reverse order of their construction.
753
754 /// Determines whether an EH cleanup is required to destroy a type
755 /// with the given destruction kind.
756 /// TODO(cir): could be shared with Clang LLVM codegen
758 switch (kind) {
760 return false;
764 return getLangOpts().Exceptions;
766 return getLangOpts().Exceptions &&
767 cgm.getCodeGenOpts().ObjCAutoRefCountExceptions;
768 }
769 llvm_unreachable("bad destruction kind");
770 }
771
775
777
778 /// Set the address of a local variable.
780 assert(!localDeclMap.count(vd) && "Decl already exists in LocalDeclMap!");
781 localDeclMap.insert({vd, addr});
782
783 // Add to the symbol table if not there already.
784 if (symbolTable.count(vd))
785 return;
786 symbolTable.insert(vd, addr.getPointer());
787 }
788
789 // Replaces the address of the local variable, if it exists. Else does the
790 // same thing as setAddrOfLocalVar.
792 localDeclMap.insert_or_assign(vd, addr);
793 }
794
795 // A class to allow reverting changes to a var-decl's registration to the
796 // localDeclMap. This is used in cases where things are being inserted into
797 // the variable list but don't follow normal lookup/search rules, like in
798 // OpenACC recipe generation.
800 CIRGenFunction &cgf;
801 const VarDecl *vd;
802 bool shouldDelete = false;
803 Address oldAddr = Address::invalid();
804
805 public:
807 : cgf(cgf), vd(vd) {
808 auto mapItr = cgf.localDeclMap.find(vd);
809
810 if (mapItr != cgf.localDeclMap.end())
811 oldAddr = mapItr->second;
812 else
813 shouldDelete = true;
814 }
815
817 if (shouldDelete)
818 cgf.localDeclMap.erase(vd);
819 else
820 cgf.localDeclMap.insert_or_assign(vd, oldAddr);
821 }
822 };
823
825
828
829 static bool
831
838
841
845 const clang::CXXRecordDecl *nearestVBase,
846 clang::CharUnits offsetFromNearestVBase,
847 bool baseIsNonVirtualPrimaryBase,
848 const clang::CXXRecordDecl *vtableClass,
849 VisitedVirtualBasesSetTy &vbases, VPtrsVector &vptrs);
850 /// Return the Value of the vtable pointer member pointed to by thisAddr.
851 mlir::Value getVTablePtr(mlir::Location loc, Address thisAddr,
852 const clang::CXXRecordDecl *vtableClass);
853
854 /// Returns whether we should perform a type checked load when loading a
855 /// virtual function for virtual calls to members of RD. This is generally
856 /// true when both vcall CFI and whole-program-vtables are enabled.
858
859 /// Source location information about the default argument or member
860 /// initializer expression we're evaluating, if any.
864
865 /// A scope within which we are constructing the fields of an object which
866 /// might use a CXXDefaultInitExpr. This stashes away a 'this' value to use if
867 /// we need to evaluate the CXXDefaultInitExpr within the evaluation.
869 public:
871 : cgf(cgf), oldCXXDefaultInitExprThis(cgf.cxxDefaultInitExprThis) {
872 cgf.cxxDefaultInitExprThis = thisAddr;
873 }
875 cgf.cxxDefaultInitExprThis = oldCXXDefaultInitExprThis;
876 }
877
878 private:
879 CIRGenFunction &cgf;
880 Address oldCXXDefaultInitExprThis;
881 };
882
883 /// The scope of a CXXDefaultInitExpr. Within this scope, the value of 'this'
884 /// is overridden to be the object under construction.
886 public:
891 cgf.cxxThisValue = cgf.cxxDefaultInitExprThis.getPointer();
892 cgf.cxxThisAlignment = cgf.cxxDefaultInitExprThis.getAlignment();
893 }
895 cgf.cxxThisValue = oldCXXThisValue;
896 cgf.cxxThisAlignment = oldCXXThisAlignment;
897 }
898
899 public:
901 mlir::Value oldCXXThisValue;
904 };
905
910
911 /// The scope of an ArrayInitLoopExpr. Within this scope, the value of the
912 /// current loop index is overridden. In order to encourage re-use of existing
913 /// array initialization, this uses a flag to determine if it is a 'no-op' or
914 /// not.
916 public:
917 ArrayInitLoopExprScope(CIRGenFunction &cgf, bool setIdx, mlir::Value index)
918 : cgf(cgf),
919 oldArrayInitIndex(setIdx
920 ? std::optional<mlir::Value>(cgf.arrayInitIndex)
921 : std::nullopt) {
922 if (setIdx)
923 cgf.arrayInitIndex = index;
924 }
926 if (oldArrayInitIndex.has_value())
927 cgf.arrayInitIndex = *oldArrayInitIndex;
928 }
929
930 private:
931 CIRGenFunction &cgf;
932 std::optional<mlir::Value> oldArrayInitIndex;
933 };
934
935 /// Get the index of the current ArrayInitLoopExpr, if any.
936 mlir::Value getArrayInitIndex() { return arrayInitIndex; }
937
939 LValue makeNaturalAlignAddrLValue(mlir::Value val, QualType ty);
940
941 /// Construct an address with the natural alignment of T. If a pointer to T
942 /// is expected to be signed, the pointer passed to this function must have
943 /// been signed, and the returned Address will have the pointer authentication
944 /// information needed to authenticate the signed pointer.
946 CharUnits alignment,
947 bool forPointeeType = false,
948 LValueBaseInfo *baseInfo = nullptr) {
949 if (alignment.isZero())
950 alignment = cgm.getNaturalTypeAlignment(t, baseInfo);
951 return Address(ptr, convertTypeForMem(t), alignment);
952 }
953
955 Address value, const CXXRecordDecl *derived,
956 llvm::iterator_range<CastExpr::path_const_iterator> path,
957 bool nullCheckValue, SourceLocation loc);
958
960 mlir::Location loc, Address baseAddr, const CXXRecordDecl *derived,
961 llvm::iterator_range<CastExpr::path_const_iterator> path,
962 bool nullCheckValue);
963
964 /// Return the VTT parameter that should be passed to a base
965 /// constructor/destructor with virtual bases.
966 /// FIXME: VTTs are Itanium ABI-specific, so the definition should move
967 /// to ItaniumCXXABI.cpp together with all the references to VTT.
968 mlir::Value getVTTParameter(GlobalDecl gd, bool forVirtualBase,
969 bool delegating);
970
973 return makeAddrLValue(addr, ty, LValueBaseInfo(source));
974 }
975
977 return LValue::makeAddr(addr, ty, baseInfo);
978 }
979
980 void initializeVTablePointers(mlir::Location loc,
981 const clang::CXXRecordDecl *rd);
982 void initializeVTablePointer(mlir::Location loc, const VPtr &vptr);
983
985
986 /// Return the address of a local variable.
988 auto it = localDeclMap.find(vd);
989 assert(it != localDeclMap.end() &&
990 "Invalid argument to getAddrOfLocalVar(), no decl!");
991 return it->second;
992 }
993
995 mlir::Type fieldType, unsigned index);
996
997 /// Given an opaque value expression, return its LValue mapping if it exists,
998 /// otherwise create one.
1000
1001 /// Given an opaque value expression, return its RValue mapping if it exists,
1002 /// otherwise create one.
1004
1005 /// Load the value for 'this'. This function is only valid while generating
1006 /// code for an C++ member function.
1007 /// FIXME(cir): this should return a mlir::Value!
1008 mlir::Value loadCXXThis() {
1009 assert(cxxThisValue && "no 'this' value for this function");
1010 return cxxThisValue;
1011 }
1013
1014 /// Load the VTT parameter to base constructors/destructors have virtual
1015 /// bases. FIXME: Every place that calls LoadCXXVTT is something that needs to
1016 /// be abstracted properly.
1017 mlir::Value loadCXXVTT() {
1018 assert(cxxStructorImplicitParamValue && "no VTT value for this function");
1020 }
1021
1022 /// Convert the given pointer to a complete class to the given direct base.
1024 Address value,
1025 const CXXRecordDecl *derived,
1026 const CXXRecordDecl *base,
1027 bool baseIsVirtual);
1028
1029 /// Determine whether a return value slot may overlap some other object.
1031 // FIXME: Assuming no overlap here breaks guaranteed copy elision for base
1032 // class subobjects. These cases may need to be revisited depending on the
1033 // resolution of the relevant core issue.
1035 }
1036
1037 /// Determine whether a base class initialization may overlap some other
1038 /// object.
1040 const CXXRecordDecl *baseRD,
1041 bool isVirtual);
1042
1043 /// Return a CIR constant for an undefined value of \p cirTy.
1044 mlir::Value getUndefConstant(mlir::Location loc, mlir::Type cirTy);
1045
1046 /// Get an appropriate 'undef' rvalue for the given type.
1048
1049 cir::FuncOp generateCode(clang::GlobalDecl gd, cir::FuncOp fn,
1050 cir::FuncType funcType);
1051
1053 FunctionArgList &args);
1054
1055 /// Emit the function prologue: declare function arguments in the symbol
1056 /// table.
1057 void emitFunctionProlog(const FunctionArgList &args, mlir::Block *entryBB,
1058 const FunctionDecl *fd, SourceLocation bodyBeginLoc);
1059
1060 /// Emit code for the start of a function.
1061 /// \param loc The location to be associated with the function.
1062 /// \param startLoc The location of the function body.
1064 cir::FuncOp fn, cir::FuncType funcType,
1066 clang::SourceLocation startLoc);
1067
1068 /// returns true if aggregate type has a volatile member.
1070 if (const auto *rd = t->getAsRecordDecl())
1071 return rd->hasVolatileMember();
1072 return false;
1073 }
1074
1075 void addCatchHandlerAttr(const CXXCatchStmt *catchStmt,
1076 SmallVector<mlir::Attribute> &handlerAttrs);
1077
1078 /// The cleanup depth enclosing all the cleanups associated with the
1079 /// parameters.
1081
1083
1084 /// Takes the old cleanup stack size and emits the cleanup blocks
1085 /// that have been added.
1086 void popCleanupBlocks(EHScopeStack::stable_iterator oldCleanupStackDepth,
1087 ArrayRef<mlir::Value *> valuesToReload = {});
1088
1089 /// Pops cleanup blocks until the given savepoint is reached, then adds the
1090 /// cleanups from the given savepoint in the lifetime-extended cleanups stack.
1091 void popCleanupBlocks(EHScopeStack::stable_iterator oldCleanupStackDepth,
1092 size_t oldLifetimeExtendedSize,
1093 ArrayRef<mlir::Value *> valuesToReload = {});
1094 void popCleanupBlock(bool forDeactivation = false);
1095
1096 /// Emit the cleanups captured for a loop's condition variable (those pushed
1097 /// above \p depth while EHScopeStack was capturing condition cleanups) at
1098 /// the current insertion point, which must be inside the loop op's cleanup
1099 /// region, and pop them off the EH stack.
1100 void emitLoopConditionCleanups(EHScopeStack::stable_iterator depth,
1101 mlir::Location loc);
1102
1103 void terminateStructuredRegionBody(mlir::Region &r, mlir::Location loc);
1104
1105 /// Deactivates the given cleanup block. The block cannot be reactivated. Pops
1106 /// it if it's the top of the stack.
1107 ///
1108 /// \param DominatingIP - An instruction which is known to
1109 /// dominate the current IP (if set) and which lies along
1110 /// all paths of execution between the current IP and the
1111 /// the point at which the cleanup comes into scope.
1112 void deactivateCleanupBlock(EHScopeStack::stable_iterator cleanup,
1113 mlir::Operation *dominatingIP);
1114
1115 /// Create an active flag variable for use with conditional cleanups. The
1116 /// flag is initialized to false before the outermost conditional and set to
1117 /// true at the current insertion point (inside the conditional branch).
1118 Address createCleanupActiveFlag();
1119
1120 /// Set up the last cleanup that was pushed as a conditional
1121 /// full-expression cleanup.
1122 void initFullExprCleanup();
1123 void initFullExprCleanupWithFlag(Address activeFlag);
1124
1125 /// Promote a single pending cleanup entry onto the EH scope stack. If the
1126 /// entry has a valid activeFlag, the cleanup is configured as conditional.
1127 /// Defined in CIRGenDecl.cpp where the concrete cleanup types are visible.
1128 void pushPendingCleanupToEHStack(const PendingCleanupEntry &entry);
1129
1130 /// Push a cleanup to be run at the end of the current full-expression. Safe
1131 /// against the possibility that we're currently inside a
1132 /// conditionally-evaluated expression.
1133 template <class T, class... As>
1135 if (!isInConditionalBranch())
1136 return ehStack.pushCleanup<T>(kind, a...);
1137
1138 // Defer the cleanup until the FullExprCleanupScope exits. We can't push
1139 // to the EH stack now because the ternary's inner LexicalScope would pop
1140 // it prematurely.
1141 Address activeFlag = createCleanupActiveFlag();
1143 PendingCleanupEntry{kind, a..., activeFlag});
1144 }
1145
1146 /// Push a cleanup and record it for deferred deactivation. The cleanup will
1147 /// be deactivated when the enclosing CleanupDeactivationScope exits.
1148 template <class T, class... As>
1150 mlir::Location loc = builder.getUnknownLoc();
1151 mlir::Operation *dominatingIP = builder.getBool(false, loc).getOperation();
1152 ehStack.pushCleanup<T>(kind, a...);
1154 {ehStack.stable_begin(), dominatingIP});
1155 }
1156
1158 Address addr, QualType type);
1160 QualType type, Destroyer *destroyer,
1161 bool useEHCleanupForArray);
1162
1163 /// Queue a cleanup to be pushed after finishing the current full-expression.
1164 /// When the enclosing RunCleanupsScope exits, popCleanupBlocks promotes these
1165 /// entries onto the EH scope stack for the enclosing scope.
1167 Destroyer *destroyer) {
1168 lifetimeExtendedCleanupStack.push_back({kind, addr, type, destroyer});
1169 }
1170
1171 /// Enters a new scope for capturing cleanups, all of which
1172 /// will be executed once the scope is exited.
1173 class RunCleanupsScope {
1174 EHScopeStack::stable_iterator cleanupStackDepth, oldCleanupStackDepth;
1175 size_t lifetimeExtendedCleanupStackSize;
1176 CleanupDeactivationScope deactivateCleanups;
1177
1178 protected:
1181
1182 private:
1183 RunCleanupsScope(const RunCleanupsScope &) = delete;
1184 void operator=(const RunCleanupsScope &) = delete;
1185
1186 protected:
1188
1189 public:
1190 /// Enter a new cleanup scope.
1192 : deactivateCleanups(cgf), performCleanup(true), cgf(cgf) {
1193 cleanupStackDepth = cgf.ehStack.stable_begin();
1194 lifetimeExtendedCleanupStackSize =
1195 cgf.lifetimeExtendedCleanupStack.size();
1196 oldDidCallStackSave = cgf.didCallStackSave;
1197 cgf.didCallStackSave = false;
1198 oldCleanupStackDepth = cgf.currentCleanupStackDepth;
1199 cgf.currentCleanupStackDepth = cleanupStackDepth;
1200 }
1201
1202 /// Exit this cleanup scope, emitting any accumulated cleanups.
1204 if (performCleanup)
1205 forceCleanup();
1206 }
1207
1208 /// Force the emission of cleanups now, instead of waiting
1209 /// until this object is destroyed.
1210 void forceCleanup(ArrayRef<mlir::Value *> valuesToReload = {}) {
1211 assert(performCleanup && "Already forced cleanup");
1213
1214 // forceDeactivate() can pop cleanup scopes that were pushed with
1215 // deferred deactivation, which moves the insertion point out of the
1216 // cleanup body region. Any caller value defined inside such a body
1217 // would no longer dominate uses past the scope. The downstream
1218 // popCleanupBlocks() handles the spill for any cleanups it pops
1219 // itself, but it cannot help with cleanups that forceDeactivate has
1220 // already popped. Spill those values here, while the insertion point
1221 // is still inside the body, so we can reload them after all popping
1222 // is done. We only spill values whose defining op lives inside a
1223 // cir.cleanup.scope, since values defined outside any cleanup scope
1224 // (e.g. allocas in the entry block) already dominate the post-scope
1225 // insertion point.
1226 const bool hasPendingDeactivations =
1228 deactivateCleanups.oldDeactivateCleanupStackSize;
1229
1230 llvm::SmallVector<Address> tempAllocas;
1231 bool didSpillAny = false;
1232 if (hasPendingDeactivations) {
1233 tempAllocas.reserve(valuesToReload.size());
1234 for (mlir::Value *valPtr : valuesToReload) {
1235 mlir::Value val = *valPtr;
1236 if (!val || !val.getDefiningOp() ||
1237 !val.getDefiningOp()->getParentOfType<cir::CleanupScopeOp>()) {
1238 tempAllocas.push_back(Address::invalid());
1239 continue;
1240 }
1242 val.getType(), val.getLoc(), "tmp.exprcleanup");
1243 tempAllocas.push_back(temp);
1244 cgf.builder.createStore(val.getLoc(), val, temp);
1245 didSpillAny = true;
1246 }
1247 }
1248
1249 deactivateCleanups.forceDeactivate();
1250 // If we already spilled some of the caller's values, don't ask
1251 // popCleanupBlocks to spill them again. Values we did not pre-spill
1252 // are not inside any cir.cleanup.scope, so they cannot be invalidated
1253 // by either forceDeactivate's or popCleanupBlocks's pops (both only
1254 // pop cir.cleanup.scope ops); they already dominate the post-scope
1255 // insertion point on their own.
1256 if (didSpillAny) {
1257 cgf.popCleanupBlocks(cleanupStackDepth,
1258 lifetimeExtendedCleanupStackSize);
1259
1260 // Reload the spilled values now that all cleanup popping (and
1261 // promotion of any lifetime-extended cleanups onto the EH stack) is
1262 // done.
1263 for (auto [addr, valPtr] : llvm::zip(tempAllocas, valuesToReload)) {
1264 if (!addr.isValid())
1265 continue;
1266 *valPtr = cgf.builder.createLoad(valPtr->getLoc(), addr);
1267 }
1268 } else {
1269 cgf.popCleanupBlocks(cleanupStackDepth,
1270 lifetimeExtendedCleanupStackSize, valuesToReload);
1271 }
1272
1273 performCleanup = false;
1274 cgf.currentCleanupStackDepth = oldCleanupStackDepth;
1275 }
1276
1277 /// Force the emission of EH cleanups now, but defer promoting any
1278 /// lifetime-extended cleanup entries onto the EH scope stack. The caller
1279 /// must subsequently call forceLifetimeExtendedCleanups() to finalize the
1280 /// scope.
1282 assert(performCleanup && "Already forced cleanup");
1283 cgf.didCallStackSave = oldDidCallStackSave;
1284 deactivateCleanups.forceDeactivate();
1285 cgf.popCleanupBlocks(cleanupStackDepth);
1286 }
1287
1288 /// Promote any pending lifetime-extended cleanup entries onto the EH scope
1289 /// stack at the current insertion point and finalize this scope. This must
1290 /// be paired with a prior call to forceCleanupExceptLifetimeExtended().
1292 assert(performCleanup && "Already forced cleanup");
1293 assert(deactivateCleanups.deactivated &&
1294 "forceCleanupExceptLifetimeExtended() must be called first");
1295 cgf.popCleanupBlocks(cleanupStackDepth, lifetimeExtendedCleanupStackSize);
1296 performCleanup = false;
1297 cgf.currentCleanupStackDepth = oldCleanupStackDepth;
1298 }
1299
1300 /// Whether there are any pending cleanups that have been pushed since
1301 /// this scope was entered.
1302 bool hasPendingCleanups() const {
1303 return cgf.ehStack.stable_begin() != cleanupStackDepth;
1304 }
1305 };
1306
1307 // Cleanup stack depth of the RunCleanupsScope that was pushed most recently.
1309
1311 CIRGenFunction &cgf;
1312 RunCleanupsScope cleanups;
1313 cir::CleanupScopeOp scope;
1314 size_t deferredCleanupStackSize;
1315 bool exited = false;
1316
1317 public:
1318 FullExprCleanupScope(CIRGenFunction &cgf, const Expr *subExpr);
1319
1320 void exit(ArrayRef<mlir::Value *> valuesToReload = {});
1321
1323 if (!exited)
1324 exit();
1325 }
1326
1327 private:
1329 void operator=(const FullExprCleanupScope &) = delete;
1330 };
1331
1332 /// Captures the destructor cleanup for a loop's condition variable so that it
1333 /// can be emitted into the loop op's per-iteration cleanup region.
1335 CIRGenFunction &cgf;
1337 bool active;
1338
1339 public:
1341 : cgf(cgf), depth(cgf.ehStack.stable_begin()), active(active) {}
1342
1343 /// An RAII class that suppresses cir.cleanup.scope creation for cleanups
1344 /// pushed onto the EH stack while a loop condition variable is being
1345 /// emitted and instead captures these cleanups so that they can be emitted
1346 /// into the loop op's cleanup region after the condition region is built.
1348 EHScopeStack &ehStack;
1349
1350 public:
1352 : ehStack(scope.cgf.ehStack) {
1353 // Capturing wraps only the condition variable's own destructor push,
1354 // which emits no nested code, so it can never already be active.
1355 assert(!ehStack.isCapturingLoopConditionCleanups() &&
1356 "loop condition cleanup capturing should not nest");
1357 if (scope.active)
1358 ehStack.setCapturingLoopConditionCleanups(true);
1359 }
1360 ~CaptureScope() { ehStack.setCapturingLoopConditionCleanups(false); }
1361
1362 CaptureScope(const CaptureScope &) = delete;
1363 void operator=(const CaptureScope &) = delete;
1364 };
1365
1366 /// Emit the captured condition-variable cleanups into the current insertion
1367 /// point (the loop's cleanup region).
1368 void emitIntoLoopCleanupRegion(mlir::Location loc) {
1369 if (active)
1370 cgf.emitLoopConditionCleanups(depth, loc);
1371 }
1372
1373 private:
1375 void operator=(const DeferredLoopConditionCleanup &) = delete;
1376 };
1377
1378public:
1379 /// Represents a scope, including function bodies, compound statements, and
1380 /// the substatements of if/while/do/for/switch/try statements. This class
1381 /// handles any automatic cleanup, along with the return value.
1382 struct LexicalScope : public RunCleanupsScope {
1383 private:
1384 // Points to the scope entry block. This is useful, for instance, for
1385 // helping to insert allocas before finalizing any recursive CodeGen from
1386 // switches.
1387 mlir::Block *entryBlock;
1388
1389 LexicalScope *parentScope = nullptr;
1390
1391 // Holds the actual value for ScopeKind::Try
1392 cir::TryOp tryOp = nullptr;
1393
1394 // On a coroutine body, the OnFallthrough sub stmt holds the handler
1395 // (CoreturnStmt) for control flow falling off the body. Keep track
1396 // of emitted co_return in this scope and allow OnFallthrough to be
1397 // skipeed.
1398 bool hasCoreturnStmt = false;
1399
1400 // Only Regular is used at the moment. Support for other kinds will be
1401 // added as the relevant statements/expressions are upstreamed.
1402 enum Kind {
1403 Regular, // cir.if, cir.scope, if_regions
1404 Ternary, // cir.ternary
1405 Switch, // cir.switch
1406 Try, // cir.try
1407 GlobalInit // cir.global initialization code
1408 };
1409 Kind scopeKind = Kind::Regular;
1410
1411 // The scope return value.
1412 mlir::Value retVal = nullptr;
1413
1414 mlir::Location beginLoc;
1415 mlir::Location endLoc;
1416
1417 public:
1418 unsigned depth = 0;
1419
1420 LexicalScope(CIRGenFunction &cgf, mlir::Location loc, mlir::Block *eb)
1421 : RunCleanupsScope(cgf), entryBlock(eb), parentScope(cgf.curLexScope),
1422 beginLoc(loc), endLoc(loc) {
1423
1424 assert(entryBlock && "LexicalScope requires an entry block");
1425 cgf.curLexScope = this;
1426 if (parentScope)
1427 ++depth;
1428
1429 if (const auto fusedLoc = mlir::dyn_cast<mlir::FusedLoc>(loc)) {
1430 assert(fusedLoc.getLocations().size() == 2 && "too many locations");
1431 beginLoc = fusedLoc.getLocations()[0];
1432 endLoc = fusedLoc.getLocations()[1];
1433 }
1434 }
1435
1436 void setRetVal(mlir::Value v) { retVal = v; }
1437
1438 void cleanup();
1439 void restore() { cgf.curLexScope = parentScope; }
1440
1443 cleanup();
1444 restore();
1445 }
1446
1447 // ---
1448 // Coroutine tracking
1449 // ---
1450 bool hasCoreturn() const { return hasCoreturnStmt; }
1451 void setCoreturn() { hasCoreturnStmt = true; }
1452
1453 // ---
1454 // Kind
1455 // ---
1456 bool isGlobalInit() { return scopeKind == Kind::GlobalInit; }
1457 bool isRegular() { return scopeKind == Kind::Regular; }
1458 bool isSwitch() { return scopeKind == Kind::Switch; }
1459 bool isTernary() { return scopeKind == Kind::Ternary; }
1460 bool isTry() { return scopeKind == Kind::Try; }
1461 cir::TryOp getClosestTryParent();
1462 void setAsGlobalInit() { scopeKind = Kind::GlobalInit; }
1463 void setAsSwitch() { scopeKind = Kind::Switch; }
1464 void setAsTernary() { scopeKind = Kind::Ternary; }
1465 void setAsTry(cir::TryOp op) {
1466 scopeKind = Kind::Try;
1467 tryOp = op;
1468 }
1469
1470 cir::TryOp getTry() {
1471 assert(isTry());
1472 return tryOp;
1473 }
1474
1475 // ---
1476 // Return handling.
1477 // ---
1478
1479 private:
1480 // On switches we need one return block per region, since cases don't
1481 // have their own scopes but are distinct regions nonetheless.
1482
1483 // TODO: This implementation should change once we have support for early
1484 // exits in MLIR structured control flow (llvm-project#161575)
1486 llvm::DenseMap<mlir::Block *, mlir::Location> retLocs;
1487 llvm::DenseMap<cir::CaseOp, unsigned> retBlockInCaseIndex;
1488 std::optional<unsigned> normalRetBlockIndex;
1489
1490 // There's usually only one ret block per scope, but this needs to be
1491 // get or create because of potential unreachable return statements, note
1492 // that for those, all source location maps to the first one found.
1493 mlir::Block *createRetBlock(CIRGenFunction &cgf, mlir::Location loc) {
1494 assert((isa_and_nonnull<cir::CaseOp>(
1495 cgf.builder.getBlock()->getParentOp()) ||
1496 retBlocks.size() == 0) &&
1497 "only switches can hold more than one ret block");
1498
1499 // Create the return block but don't hook it up just yet.
1500 mlir::OpBuilder::InsertionGuard guard(cgf.builder);
1501 auto *b = cgf.builder.createBlock(cgf.builder.getBlock()->getParent());
1502 retBlocks.push_back(b);
1503 updateRetLoc(b, loc);
1504 return b;
1505 }
1506
1507 cir::ReturnOp emitReturn(mlir::Location loc);
1508 void emitImplicitReturn();
1509
1510 public:
1512 mlir::Location getRetLoc(mlir::Block *b) { return retLocs.at(b); }
1513 void updateRetLoc(mlir::Block *b, mlir::Location loc) {
1514 retLocs.insert_or_assign(b, loc);
1515 }
1516
1517 mlir::Block *getOrCreateRetBlock(CIRGenFunction &cgf, mlir::Location loc) {
1518 // Check if we're inside a case region
1519 if (auto caseOp = mlir::dyn_cast_if_present<cir::CaseOp>(
1520 cgf.builder.getBlock()->getParentOp())) {
1521 auto iter = retBlockInCaseIndex.find(caseOp);
1522 if (iter != retBlockInCaseIndex.end()) {
1523 // Reuse existing return block
1524 mlir::Block *ret = retBlocks[iter->second];
1525 updateRetLoc(ret, loc);
1526 return ret;
1527 }
1528 // Create new return block
1529 mlir::Block *ret = createRetBlock(cgf, loc);
1530 retBlockInCaseIndex[caseOp] = retBlocks.size() - 1;
1531 return ret;
1532 }
1533
1534 if (normalRetBlockIndex) {
1535 mlir::Block *ret = retBlocks[*normalRetBlockIndex];
1536 updateRetLoc(ret, loc);
1537 return ret;
1538 }
1539
1540 mlir::Block *ret = createRetBlock(cgf, loc);
1541 normalRetBlockIndex = retBlocks.size() - 1;
1542 return ret;
1543 }
1544
1545 mlir::Block *getEntryBlock() { return entryBlock; }
1546 };
1547
1549
1551
1553 QualType type);
1554
1555 void pushDestroy(QualType::DestructionKind dtorKind, Address addr,
1556 QualType type);
1557
1559 Destroyer *destroyer);
1560
1562 QualType type, Destroyer *destroyer,
1563 bool useEHCleanupForArray);
1564
1566
1567 void pushIrregularPartialArrayCleanup(mlir::Value arrayBegin,
1568 Address arrayEndPointer,
1569 QualType elementType,
1570 CharUnits elementAlign,
1571 Destroyer *destroyer);
1572
1573 /// Start generating a thunk function.
1574 void startThunk(cir::FuncOp fn, GlobalDecl gd,
1575 const CIRGenFunctionInfo &fnInfo, bool isUnprototyped);
1576
1577 /// Finish generating a thunk function.
1578 void finishThunk();
1579
1580 /// Generate code for a thunk function.
1581 void generateThunk(cir::FuncOp fn, const CIRGenFunctionInfo &fnInfo,
1582 GlobalDecl gd, const ThunkInfo &thunk,
1583 bool isUnprototyped);
1584
1585 /// ----------------------
1586 /// CIR emit functions
1587 /// ----------------------
1588public:
1589 bool getAArch64SVEProcessedOperands(unsigned builtinID, const CallExpr *expr,
1591 clang::SVETypeFlags typeFlags);
1592 mlir::Value emitSVEPredicateCast(mlir::Value pred, unsigned minNumElts,
1593 mlir::Location loc);
1594 std::optional<mlir::Value>
1595 emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr,
1597 llvm::Triple::ArchType arch);
1598 std::optional<mlir::Value> emitAArch64SMEBuiltinExpr(unsigned builtinID,
1599 const CallExpr *expr);
1600 std::optional<mlir::Value> emitAArch64SVEBuiltinExpr(unsigned builtinID,
1601 const CallExpr *expr);
1602
1603 mlir::Value emitAlignmentAssumption(mlir::Value ptrValue, QualType ty,
1604 SourceLocation loc,
1605 SourceLocation assumptionLoc,
1606 int64_t alignment,
1607 mlir::Value offsetValue = nullptr);
1608
1609 mlir::Value emitAlignmentAssumption(mlir::Value ptrValue, const Expr *expr,
1610 SourceLocation assumptionLoc,
1611 int64_t alignment,
1612 mlir::Value offsetValue = nullptr);
1613
1614private:
1615 void emitAndUpdateRetAlloca(clang::QualType type, mlir::Location loc,
1616 clang::CharUnits alignment);
1617
1618 CIRGenCallee emitDirectCallee(const GlobalDecl &gd);
1619
1620public:
1622 llvm::StringRef fieldName,
1623 unsigned fieldIndex);
1624
1625 mlir::Value emitAlloca(llvm::StringRef name, mlir::Type ty,
1626 mlir::Location loc, clang::CharUnits alignment,
1627 bool insertIntoFnEntryBlock,
1628 mlir::Value arraySize = nullptr);
1629 mlir::Value emitAlloca(llvm::StringRef name, mlir::Type ty,
1630 mlir::Location loc, clang::CharUnits alignment,
1631 mlir::OpBuilder::InsertPoint ip,
1632 mlir::Value arraySize = nullptr);
1633
1634 void emitAggregateStore(mlir::Value value, Address dest);
1635
1636 void emitAggExpr(const clang::Expr *e, AggValueSlot slot);
1637
1639
1641
1642 /// Emit an aggregate copy.
1643 ///
1644 /// \param isVolatile \c true iff either the source or the destination is
1645 /// volatile.
1646 /// \param MayOverlap Whether the tail padding of the destination might be
1647 /// occupied by some other object. More efficient code can often be
1648 /// generated if not.
1649 void emitAggregateCopy(LValue dest, LValue src, QualType eltTy,
1650 AggValueSlot::Overlap_t mayOverlap,
1651 bool isVolatile = false);
1652
1653 /// Emit code to compute the specified expression which can have any type. The
1654 /// result is returned as an RValue struct. If this is an aggregate
1655 /// expression, the aggloc/agglocvolatile arguments indicate where the result
1656 /// should be returned.
1659 bool ignoreResult = false);
1660
1661 /// Emits the code necessary to evaluate an arbitrary expression into the
1662 /// given memory location.
1663 void emitAnyExprToMem(const Expr *e, Address location, Qualifiers quals,
1664 bool isInitializer);
1665
1666 /// Similarly to emitAnyExpr(), however, the result will always be accessible
1667 /// even if no aggregate location is provided.
1669
1670 void emitAnyExprToExn(const Expr *e, Address addr);
1671
1672 void emitArrayDestroy(mlir::Value begin, mlir::Value numElements,
1673 QualType elementType, CharUnits elementAlign,
1674 Destroyer *destroyer);
1675
1676 mlir::Value emitArrayLength(const clang::ArrayType *arrayType,
1677 QualType &baseType, Address &addr);
1680
1682
1684 LValueBaseInfo *baseInfo = nullptr);
1685
1686 std::pair<mlir::Value, mlir::Type>
1688 QualType inputType, std::string &constraintString,
1689 SourceLocation loc);
1690 std::pair<mlir::Value, mlir::Type>
1691 emitAsmInput(const TargetInfo::ConstraintInfo &info, const Expr *inputExpr,
1692 std::string &constraintString);
1693 mlir::LogicalResult emitAsmStmt(const clang::AsmStmt &s);
1694
1696 void emitAtomicInit(Expr *init, LValue dest);
1697 void emitAtomicStore(RValue rvalue, LValue dest, bool isInit);
1698 void emitAtomicStore(RValue rvalue, LValue dest, cir::MemOrder order,
1699 bool isVolatile, bool isInit);
1701 const Expr *memOrder, bool isStore, bool isLoad, bool isFence,
1702 llvm::function_ref<void(cir::MemOrder)> emitAtomicOp);
1703
1704 mlir::Value makeBinaryAtomicValue(
1705 cir::AtomicFetchKind kind, const clang::CallExpr *expr,
1706 mlir::Type *originalArgType = nullptr,
1707 mlir::Value *emittedArgValue = nullptr,
1708 cir::MemOrder ordering = cir::MemOrder::SequentiallyConsistent);
1709
1710 mlir::LogicalResult emitAttributedStmt(const AttributedStmt &s);
1711
1712 AutoVarEmission emitAutoVarAlloca(const clang::VarDecl &d,
1713 mlir::OpBuilder::InsertPoint ip = {});
1714
1716 AggValueSlot slot = AggValueSlot::ignored());
1718
1719 /// Emit code and set up symbol table for a variable declaration with auto,
1720 /// register, or no storage class specifier. These turn into simple stack
1721 /// objects, globals depending on target.
1722 void emitAutoVarDecl(const clang::VarDecl &d);
1723
1724 void emitAutoVarCleanups(const AutoVarEmission &emission);
1725
1726 /// Emit a loop's condition-variable declaration. This needs special handling
1727 /// so that we can manage per-iteration cleanups for the loop condition.
1729 DeferredLoopConditionCleanup &condCleanup);
1730
1731 /// Emit the initializer for an allocated variable. If this call is not
1732 /// associated with the call to emitAutoVarAlloca (as the address of the
1733 /// emission is not directly an alloca), the allocatedSeparately parameter can
1734 /// be used to suppress the assertions. However, this should only be used in
1735 /// extreme cases, as it doesn't properly reflect the language/AST.
1736 void emitAutoVarInit(const AutoVarEmission &emission);
1737 void emitAutoVarTypeCleanup(const AutoVarEmission &emission,
1739
1740 void maybeEmitDeferredVarDeclInit(const VarDecl *vd);
1741
1742 void emitBaseInitializer(mlir::Location loc, const CXXRecordDecl *classDecl,
1743 CXXCtorInitializer *baseInit);
1744
1746
1747 mlir::LogicalResult emitBreakStmt(const clang::BreakStmt &s);
1748
1749 RValue emitBuiltinExpr(const clang::GlobalDecl &gd, unsigned builtinID,
1750 const clang::CallExpr *e, ReturnValueSlot returnValue);
1751
1752 /// Returns a Value corresponding to the size of the given expression by
1753 /// emitting a `cir.objsize` operation.
1754 ///
1755 /// \param e The expression whose object size to compute
1756 /// \param type Determines the semantics of the object size computation.
1757 /// The type parameter is a 2-bit value where:
1758 /// bit 0 (type & 1): 0 = whole object, 1 = closest subobject
1759 /// bit 1 (type & 2): 0 = maximum size, 2 = minimum size
1760 /// \param resType The result type for the size value
1761 /// \param emittedE Optional pre-emitted pointer value. If non-null, we'll
1762 /// call `cir.objsize` on this value rather than emitting e.
1763 /// \param isDynamic If true, allows runtime evaluation via dynamic mode
1764 mlir::Value emitBuiltinObjectSize(const clang::Expr *e, unsigned type,
1765 cir::IntType resType, mlir::Value emittedE,
1766 bool isDynamic);
1767
1768 mlir::Value evaluateOrEmitBuiltinObjectSize(const clang::Expr *e,
1769 unsigned type,
1770 cir::IntType resType,
1771 mlir::Value emittedE,
1772 bool isDynamic);
1773
1774 int64_t getAccessedFieldNo(unsigned idx, mlir::ArrayAttr elts);
1775
1777
1778 /// Emit a simple LLVM intrinsic that takes N scalar arguments. The intrinsic
1779 /// name is used verbatim; any overload mangling (e.g. `.f32`, `.p1`) must be
1780 /// baked into \p intrinName by the caller. The result type defaults to the
1781 /// type of the first argument; pass \p resultType for intrinsics whose result
1782 /// differs from the operand, such as a vector reduction that returns the
1783 /// element type. Unlike classic CodeGen, CIR has no intrinsic registry to
1784 /// derive the result type from the operand, so it must be supplied here.
1785 template <unsigned N>
1786 [[maybe_unused]] RValue
1788 llvm::StringRef intrinName,
1789 mlir::Type resultType = {}) {
1790 static_assert(N, "expect non-empty argument");
1791 mlir::Type cirTy =
1792 resultType ? resultType : convertType(e->getArg(0)->getType());
1794 for (unsigned i = 0; i < N; ++i)
1795 args.push_back(emitScalarExpr(e->getArg(i)));
1796 const auto call = cir::LLVMIntrinsicCallOp::create(
1797 builder, getLoc(e->getExprLoc()), builder.getStringAttr(intrinName),
1798 cirTy, args);
1799 return RValue::get(call->getResult(0));
1800 }
1801
1802 RValue emitCall(const CIRGenFunctionInfo &funcInfo,
1803 const CIRGenCallee &callee, ReturnValueSlot returnValue,
1804 const CallArgList &args, cir::CIRCallOpInterface *callOp,
1805 mlir::Location loc);
1808 const CallArgList &args,
1809 cir::CIRCallOpInterface *callOrTryCall = nullptr) {
1810 assert(currSrcLoc && "source location must have been set");
1811 return emitCall(funcInfo, callee, returnValue, args, callOrTryCall,
1812 *currSrcLoc);
1813 }
1814
1815 RValue emitCall(clang::QualType calleeTy, const CIRGenCallee &callee,
1817
1818 /// Emit the call and return for a thunk function.
1819 void emitCallAndReturnForThunk(cir::FuncOp callee, const ThunkInfo *thunk,
1820 bool isUnprototyped);
1821
1822 void emitCallArg(CallArgList &args, const clang::Expr *e,
1823 clang::QualType argType);
1824 void emitCallArgs(
1825 CallArgList &args, PrototypeWrapper prototype,
1826 llvm::iterator_range<clang::CallExpr::const_arg_iterator> argRange,
1827 AbstractCallee callee = AbstractCallee(), unsigned paramsToSkip = 0);
1831
1835
1836 template <typename T>
1837 mlir::LogicalResult emitCaseDefaultCascade(const T *stmt, mlir::Type condType,
1838 mlir::ArrayAttr value,
1839 cir::CaseOpKind kind,
1840 bool buildingTopLevelCase);
1841
1843
1844 mlir::LogicalResult emitCaseStmt(const clang::CaseStmt &s,
1845 mlir::Type condType,
1846 bool buildingTopLevelCase);
1847
1848 LValue emitCastLValue(const CastExpr *e);
1849
1850 /// Emits an argument for a call to a `__builtin_assume`. If the builtin
1851 /// sanitizer is enabled, a runtime check is also emitted.
1852 mlir::Value emitCheckedArgForAssume(const Expr *e);
1853
1854 /// Emit a conversion from the specified complex type to the specified
1855 /// destination type, where the destination type is an LLVM scalar type.
1856 mlir::Value emitComplexToScalarConversion(mlir::Value src, QualType srcTy,
1857 QualType dstTy, SourceLocation loc);
1858
1861
1863
1864 mlir::LogicalResult emitCoroutineBody(const CoroutineBodyStmt &s);
1865 cir::CallOp emitCoroEndBuiltinCall(mlir::Location loc, mlir::Value nullPtr);
1866 cir::CallOp emitCoroIDBuiltinCall(mlir::Location loc, mlir::Value nullPtr);
1867 cir::CallOp emitCoroAllocBuiltinCall(mlir::Location loc);
1868 cir::CallOp emitCoroBeginBuiltinCall(mlir::Location loc,
1869 mlir::Value coroframeAddr);
1870
1871 cir::CallOp emitCoroFreeBuiltin(const CallExpr *e);
1873
1874 void emitDestroy(Address addr, QualType type, Destroyer *destroyer);
1875
1877
1878 mlir::LogicalResult emitContinueStmt(const clang::ContinueStmt &s);
1879
1880 mlir::LogicalResult emitCoreturnStmt(const CoreturnStmt &s);
1881
1883 AggValueSlot dest);
1884
1887 Address arrayBegin, const CXXConstructExpr *e,
1888 bool newPointerIsChecked,
1889 bool zeroInitialize = false);
1891 mlir::Value numElements, Address arrayBase,
1892 const CXXConstructExpr *e,
1893 bool newPointerIsChecked, bool zeroInitialize,
1894 Address endOfInit);
1896 clang::CXXCtorType type, bool forVirtualBase,
1897 bool delegating, AggValueSlot thisAVS,
1898 const clang::CXXConstructExpr *e);
1899
1901 clang::CXXCtorType type, bool forVirtualBase,
1902 bool delegating, Address thisAddr,
1904
1906 bool forVirtualBase, Address thisAddr,
1907 bool inheritedFromVBase,
1908 const CXXInheritedCtorInitExpr *e);
1909
1911 SourceLocation loc, const CXXConstructorDecl *d, CXXCtorType ctorType,
1912 bool forVirtualBase, bool delegating, CallArgList &args);
1913
1914 void emitCXXDeleteExpr(const CXXDeleteExpr *e);
1915
1917 bool forVirtualBase, bool delegating,
1918 Address thisAddr, QualType thisTy);
1919
1921 mlir::Value thisVal, QualType thisTy,
1922 mlir::Value implicitParam,
1923 QualType implicitParamTy, const CallExpr *e);
1924
1925 mlir::LogicalResult emitCXXForRangeStmt(const CXXForRangeStmt &s,
1927
1930
1932 const Expr *e, Address base, mlir::Value memberPtr,
1933 const MemberPointerType *memberPtrType, LValueBaseInfo *baseInfo);
1934
1936 const clang::CXXMethodDecl *md, const CIRGenCallee &callee,
1937 ReturnValueSlot returnValue, mlir::Value thisPtr,
1938 mlir::Value implicitParam, clang::QualType implicitParamTy,
1939 const clang::CallExpr *ce, CallArgList *rtlArgs);
1940
1942 const clang::CallExpr *ce, const clang::CXXMethodDecl *md,
1943 ReturnValueSlot returnValue, bool hasQualifier,
1944 clang::NestedNameSpecifier qualifier, bool isArrow,
1945 const clang::Expr *base);
1946
1949
1950 mlir::Value emitCXXNewExpr(const CXXNewExpr *e);
1951
1952 void emitNewArrayInitializer(const CXXNewExpr *e, QualType elementType,
1953 mlir::Type elementTy, Address beginPtr,
1954 mlir::Value numElements,
1955 mlir::Value allocSizeWithoutCookie);
1956
1957 /// Create a check for a function parameter that may potentially be
1958 /// declared as non-null.
1959 void emitNonNullArgCheck(RValue rv, QualType argType, SourceLocation argLoc,
1960 AbstractCallee ac, unsigned paramNum);
1961
1963 const CXXMethodDecl *md,
1965
1968
1970
1972 const CallExpr *callExpr,
1974
1975 void emitCXXTemporary(const CXXTemporary *temporary, QualType tempType,
1976 Address ptr);
1977
1978 void emitCXXThrowExpr(const CXXThrowExpr *e);
1979
1981 virtual mlir::LogicalResult operator()(CIRGenFunction &cgf) = 0;
1982 virtual ~cxxTryBodyEmitter() = default;
1983 };
1984
1985 void emitBeginCatch(const CXXCatchStmt *catchStmt, mlir::Value ehToken);
1986
1987 mlir::LogicalResult emitCXXTryStmt(const clang::CXXTryStmt &s,
1988 cxxTryBodyEmitter &bodyCallback);
1989 mlir::LogicalResult emitCXXTryStmt(const clang::CXXTryStmt &s);
1990
1992 clang::CXXCtorType ctorType, FunctionArgList &args);
1993
1994 // It's important not to confuse this and emitDelegateCXXConstructorCall.
1995 // Delegating constructors are the C++11 feature. The constructor delegate
1996 // optimization is used to reduce duplication in the base and complete
1997 // constructors where they are substantially the same.
1999 const FunctionArgList &args);
2000
2001 void emitDeleteCall(const FunctionDecl *deleteFD, mlir::Value ptr,
2002 QualType deleteTy);
2003
2004 mlir::LogicalResult emitDoStmt(const clang::DoStmt &s);
2005
2006 mlir::Value emitCXXTypeidExpr(const CXXTypeidExpr *e);
2007 mlir::Value emitDynamicCast(Address thisAddr, const CXXDynamicCastExpr *dce);
2008
2009 /// Emit an expression as an initializer for an object (variable, field, etc.)
2010 /// at the given location. The expression is not necessarily the normal
2011 /// initializer for the object, and the address is not necessarily
2012 /// its normal location.
2013 ///
2014 /// \param init the initializing expression
2015 /// \param d the object to act as if we're initializing
2016 /// \param lvalue the lvalue to initialize
2017 /// \param capturedByInit true if \p d is a __block variable whose address is
2018 /// potentially changed by the initializer
2019 void emitExprAsInit(const clang::Expr *init, const clang::ValueDecl *d,
2020 LValue lvalue, bool capturedByInit = false);
2021
2022 mlir::LogicalResult emitFunctionBody(const clang::Stmt *body);
2023
2024 mlir::LogicalResult emitGotoStmt(const clang::GotoStmt &s);
2025
2026 mlir::LogicalResult emitIndirectGotoStmt(const IndirectGotoStmt &s);
2027
2029
2031 clang::Expr *init);
2032
2034
2035 mlir::Value emitPromotedComplexExpr(const Expr *e, QualType promotionType);
2036
2037 mlir::Value emitPromotedScalarExpr(const Expr *e, QualType promotionType);
2038
2039 mlir::Value emitPromotedValue(mlir::Value result, QualType promotionType);
2040
2041 void emitReturnOfRValue(mlir::Location loc, RValue rv, QualType ty);
2042
2043 mlir::Value emitRuntimeCall(mlir::Location loc, cir::FuncOp callee,
2045 mlir::NamedAttrList attrs = {});
2046
2047 void emitInvariantStart(CharUnits size, mlir::Value addr, mlir::Location loc);
2048
2049 /// Emit the computation of the specified expression of scalar type.
2050 mlir::Value emitScalarExpr(const clang::Expr *e,
2051 bool ignoreResultAssign = false);
2052
2053 mlir::Value emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv);
2054
2055 /// Build a debug stoppoint if we are emitting debug info.
2056 void emitStopPoint(const Stmt *s);
2057
2058 // Build CIR for a statement. useCurrentScope should be true if no
2059 // new scopes need be created when finding a compound statement.
2060 mlir::LogicalResult emitStmt(const clang::Stmt *s, bool useCurrentScope,
2061 llvm::ArrayRef<const Attr *> attrs = {});
2062
2063 mlir::LogicalResult emitSimpleStmt(const clang::Stmt *s,
2064 bool useCurrentScope);
2065
2066 mlir::LogicalResult emitForStmt(const clang::ForStmt &s);
2067
2068 void emitForwardingCallToLambda(const CXXMethodDecl *lambdaCallOperator,
2069 CallArgList &callArgs);
2070
2071 RValue emitCoawaitExpr(const CoawaitExpr &e,
2072 AggValueSlot aggSlot = AggValueSlot::ignored(),
2073 bool ignoreResult = false);
2074
2075 RValue emitCoyieldExpr(const CoyieldExpr &e,
2076 AggValueSlot aggSlot = AggValueSlot::ignored(),
2077 bool ignoreResult = false);
2078 /// Emit the computation of the specified expression of complex type,
2079 /// returning the result.
2080 mlir::Value emitComplexExpr(const Expr *e);
2081
2082 void emitComplexExprIntoLValue(const Expr *e, LValue dest, bool isInit);
2083
2084 mlir::Value emitComplexPrePostIncDec(const UnaryOperator *e, LValue lv);
2085
2086 LValue emitComplexAssignmentLValue(const BinaryOperator *e);
2087 LValue emitComplexCompoundAssignmentLValue(const CompoundAssignOperator *e);
2088 LValue emitScalarCompoundAssignWithComplex(const CompoundAssignOperator *e,
2089 mlir::Value &result);
2090
2091 mlir::LogicalResult
2092 emitCompoundStmt(const clang::CompoundStmt &s, Address *lastValue = nullptr,
2093 AggValueSlot slot = AggValueSlot::ignored());
2094
2095 mlir::LogicalResult
2097 Address *lastValue = nullptr,
2098 AggValueSlot slot = AggValueSlot::ignored());
2099
2100 void emitDecl(const clang::Decl &d, bool evaluateConditionDecl = false);
2101 mlir::LogicalResult emitDeclStmt(const clang::DeclStmt &s);
2102 LValue emitDeclRefLValue(const clang::DeclRefExpr *e);
2103
2104 mlir::LogicalResult emitDefaultStmt(const clang::DefaultStmt &s,
2105 mlir::Type condType,
2106 bool buildingTopLevelCase);
2107
2109 clang::CXXCtorType ctorType,
2110 const FunctionArgList &args,
2112
2113 /// We are performing a delegate call; that is, the current function is
2114 /// delegating to another one. Produce a r-value suitable for passing the
2115 /// given parameter.
2116 void emitDelegateCallArg(CallArgList &args, const clang::VarDecl *param,
2118
2119 /// Emit an `if` on a boolean condition to the specified blocks.
2120 /// FIXME: Based on the condition, this might try to simplify the codegen of
2121 /// the conditional based on the branch.
2122 /// In the future, we may apply code generation simplifications here,
2123 /// similar to those used in classic LLVM codegen
2124 /// See `EmitBranchOnBoolExpr` for inspiration.
2125 mlir::LogicalResult emitIfOnBoolExpr(const clang::Expr *cond,
2126 const clang::Stmt *thenS,
2127 const clang::Stmt *elseS);
2128 cir::IfOp emitIfOnBoolExpr(const clang::Expr *cond,
2129 BuilderCallbackRef thenBuilder,
2130 mlir::Location thenLoc,
2131 BuilderCallbackRef elseBuilder,
2132 std::optional<mlir::Location> elseLoc = {});
2133
2134 mlir::Value emitOpOnBoolExpr(mlir::Location loc, const clang::Expr *cond);
2135
2136 LValue emitPointerToDataMemberBinaryExpr(const BinaryOperator *e);
2137
2138 mlir::LogicalResult emitLabel(const clang::LabelDecl &d);
2139 mlir::LogicalResult emitLabelStmt(const clang::LabelStmt &s);
2140
2141 void emitLambdaDelegatingInvokeBody(const CXXMethodDecl *md);
2142 void emitLambdaStaticInvokeBody(const CXXMethodDecl *md);
2143
2144 mlir::LogicalResult emitIfStmt(const clang::IfStmt &s);
2145
2146 /// Emit code to compute the specified expression,
2147 /// ignoring the result.
2148 void emitIgnoredExpr(const clang::Expr *e);
2149
2150 RValue emitLoadOfBitfieldLValue(LValue lv, SourceLocation loc);
2151
2152 /// Load a complex number from the specified l-value.
2153 mlir::Value emitLoadOfComplex(LValue src, SourceLocation loc);
2154
2155 RValue emitLoadOfExtVectorElementLValue(LValue lv);
2156
2157 /// Given an expression that represents a value lvalue, this method emits
2158 /// the address of the lvalue, then loads the result as an rvalue,
2159 /// returning the rvalue.
2160 RValue emitLoadOfLValue(LValue lv, SourceLocation loc);
2161
2162 Address emitLoadOfReference(LValue refLVal, mlir::Location loc,
2163 LValueBaseInfo *pointeeBaseInfo);
2164 LValue emitLoadOfReferenceLValue(Address refAddr, mlir::Location loc,
2165 QualType refTy, AlignmentSource source);
2166
2167 /// EmitLoadOfScalar - Load a scalar value from an address, taking
2168 /// care to appropriately convert from the memory representation to
2169 /// the LLVM value representation. The l-value must be a simple
2170 /// l-value.
2171 mlir::Value emitLoadOfScalar(LValue lvalue, SourceLocation loc);
2172 mlir::Value emitLoadOfScalar(Address addr, bool isVolatile, QualType ty,
2173 SourceLocation loc, LValueBaseInfo baseInfo,
2174 bool isNontemporal = false);
2175
2176 /// Emit code to compute a designator that specifies the location
2177 /// of the expression.
2178 /// FIXME: document this function better.
2179 LValue emitLValue(const clang::Expr *e);
2180 LValue emitLValueForBitField(LValue base, const FieldDecl *field);
2181 LValue emitLValueForField(LValue base, const clang::FieldDecl *field);
2182
2183 LValue emitLValueForLambdaField(const FieldDecl *field);
2184 LValue emitLValueForLambdaField(const FieldDecl *field,
2185 mlir::Value thisValue);
2186
2187 /// Like emitLValueForField, excpet that if the Field is a reference, this
2188 /// will return the address of the reference and not the address of the value
2189 /// stored in the reference.
2190 LValue emitLValueForFieldInitialization(LValue base,
2191 const clang::FieldDecl *field,
2192 llvm::StringRef fieldName);
2193
2194 LValue emitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *e);
2195
2196 LValue emitMemberExpr(const MemberExpr *e);
2197
2198 /// Emit a musttail call for a thunk with a potentially different ABI.
2199 void emitMustTailThunk(GlobalDecl gd, mlir::Value adjustedThisPtr,
2200 cir::FuncOp callee);
2201
2202 /// Emit a call to an AMDGPU builtin function.
2203 std::optional<mlir::Value> emitAMDGPUBuiltinExpr(unsigned builtinID,
2204 const CallExpr *expr);
2205
2206 /// Emit a call to an NVPTX builtin function.
2207 std::optional<mlir::Value> emitNVPTXBuiltinExpr(unsigned builtinID,
2208 const CallExpr *expr);
2209
2210 /// Emit a device-side printf call for NVPTX targets.
2211 mlir::Value emitNVPTXDevicePrintfCallExpr(const CallExpr *expr);
2212
2213 LValue emitOpaqueValueLValue(const OpaqueValueExpr *e);
2214
2215 LValue emitConditionalOperatorLValue(const AbstractConditionalOperator *expr);
2216
2217 /// Given an expression with a pointer type, emit the value and compute our
2218 /// best estimate of the alignment of the pointee.
2219 ///
2220 /// One reasonable way to use this information is when there's a language
2221 /// guarantee that the pointer must be aligned to some stricter value, and
2222 /// we're simply trying to ensure that sufficiently obvious uses of under-
2223 /// aligned objects don't get miscompiled; for example, a placement new
2224 /// into the address of a local variable. In such a case, it's quite
2225 /// reasonable to just ignore the returned alignment when it isn't from an
2226 /// explicit source.
2227 Address emitPointerWithAlignment(const clang::Expr *expr,
2228 LValueBaseInfo *baseInfo = nullptr);
2229
2230 /// Emits a reference binding to the passed in expression.
2231 RValue emitReferenceBindingToExpr(const Expr *e);
2232
2233 mlir::LogicalResult emitReturnStmt(const clang::ReturnStmt &s);
2234
2235 RValue emitRotate(const CallExpr *e, bool isRotateLeft);
2236
2237 mlir::Value emitScalarConstant(const ConstantEmission &constant, Expr *e);
2238
2239 /// Emit a conversion from the specified type to the specified destination
2240 /// type, both of which are CIR scalar types.
2241 mlir::Value emitScalarConversion(mlir::Value src, clang::QualType srcType,
2242 clang::QualType dstType,
2243 clang::SourceLocation loc);
2244
2245 void emitScalarInit(const clang::Expr *init, mlir::Location loc,
2246 LValue lvalue, bool capturedByInit = false);
2247
2248 mlir::Value emitScalarOrConstFoldImmArg(unsigned iceArguments, unsigned idx,
2249 const Expr *argExpr);
2250
2251 void emitStaticVarDecl(const VarDecl &d, cir::GlobalLinkageKind linkage);
2252
2253 /// Emit a guarded initializer for a static local variable.
2254 void emitCXXGuardedInit(const VarDecl &varDecl, cir::GlobalOp globalOp,
2255 bool performInit);
2256
2257 void emitStoreOfComplex(mlir::Location loc, mlir::Value v, LValue dest,
2258 bool isInit);
2259
2260 void emitStoreOfScalar(mlir::Value value, Address addr, bool isVolatile,
2261 clang::QualType ty, LValueBaseInfo baseInfo,
2262 bool isInit = false, bool isNontemporal = false);
2263 void emitStoreOfScalar(mlir::Value value, LValue lvalue, bool isInit);
2264
2265 void emitStoreThroughExtVectorComponentLValue(RValue src, LValue dst);
2266
2267 /// Store the specified rvalue into the specified
2268 /// lvalue, where both are guaranteed to the have the same type, and that
2269 /// type is 'Ty'.
2270 void emitStoreThroughLValue(RValue src, LValue dst, bool isInit = false);
2271
2272 mlir::Value emitStoreThroughBitfieldLValue(RValue src, LValue dstresult);
2273
2274 LValue emitStringLiteralLValue(const StringLiteral *e,
2275 llvm::StringRef name = ".str");
2276
2277 mlir::LogicalResult emitSwitchBody(const clang::Stmt *s);
2278 mlir::LogicalResult emitSwitchCase(const clang::SwitchCase &s,
2279 bool buildingTopLevelCase);
2280 mlir::LogicalResult emitSwitchStmt(const clang::SwitchStmt &s);
2281
2282 std::optional<mlir::Value>
2283 emitTargetBuiltinExpr(unsigned builtinID, const clang::CallExpr *e,
2284 ReturnValueSlot &returnValue);
2285
2286 /// Given a value and its clang type, returns the value casted to its memory
2287 /// representation.
2288 /// Note: CIR defers most of the special casting to the final lowering passes
2289 /// to conserve the high level information.
2290 mlir::Value emitToMemory(mlir::Value value, clang::QualType ty);
2291
2292 /// EmitFromMemory - Change a scalar value from its memory
2293 /// representation to its value representation.
2294 mlir::Value emitFromMemory(mlir::Value value, clang::QualType ty);
2295
2296 /// Emit a trap instruction, which is used to abort the program in an abnormal
2297 /// way, usually for debugging purposes.
2298 /// \p createNewBlock indicates whether to create a new block for the IR
2299 /// builder. Since the `cir.trap` operation is a terminator, operations that
2300 /// follow a trap cannot be emitted after `cir.trap` in the same block. To
2301 /// ensure these operations get emitted successfully, you need to create a new
2302 /// dummy block and set the insertion point there before continuing from the
2303 /// trap operation.
2304 void emitTrap(mlir::Location loc, bool createNewBlock);
2305
2306 LValue emitUnaryOpLValue(const clang::UnaryOperator *e);
2307
2308 mlir::Value emitUnPromotedValue(mlir::Value result, QualType unPromotionType);
2309
2310 /// Emit a reached-unreachable diagnostic if \p loc is valid and runtime
2311 /// checking is enabled. Otherwise, just emit an unreachable instruction.
2312 /// \p createNewBlock indicates whether to create a new block for the IR
2313 /// builder. Since the `cir.unreachable` operation is a terminator, operations
2314 /// that follow an unreachable point cannot be emitted after `cir.unreachable`
2315 /// in the same block. To ensure these operations get emitted successfully,
2316 /// you need to create a dummy block and set the insertion point there before
2317 /// continuing from the unreachable point.
2318 void emitUnreachable(clang::SourceLocation loc, bool createNewBlock);
2319
2320 /// This method handles emission of any variable declaration
2321 /// inside a function, including static vars etc.
2322 void emitVarDecl(const clang::VarDecl &d);
2323
2324 void emitVariablyModifiedType(QualType ty);
2325
2326 mlir::LogicalResult emitWhileStmt(const clang::WhileStmt &s);
2327
2328 std::optional<mlir::Value> emitRISCVBuiltinExpr(unsigned builtinID,
2329 const CallExpr *expr);
2330
2331 std::optional<mlir::Value> emitX86BuiltinExpr(unsigned builtinID,
2332 const CallExpr *expr);
2333
2334 /// Given an assignment `*lhs = rhs`, emit a test that checks if \p rhs is
2335 /// nonnull, if 1\p LHS is marked _Nonnull.
2336 void emitNullabilityCheck(LValue lhs, mlir::Value rhs,
2337 clang::SourceLocation loc);
2338
2339 /// An object to manage conditionally-evaluated expressions.
2341 CIRGenFunction &cgf;
2342 mlir::OpBuilder::InsertPoint insertPt;
2343
2344 public:
2346 : cgf(cgf), insertPt(cgf.builder.saveInsertionPoint()) {}
2347 ConditionalEvaluation(CIRGenFunction &cgf, mlir::OpBuilder::InsertPoint ip)
2348 : cgf(cgf), insertPt(ip) {}
2349
2351 assert(cgf.outermostConditional != this);
2352 if (!cgf.outermostConditional)
2353 cgf.outermostConditional = this;
2354 }
2355
2357 assert(cgf.outermostConditional != nullptr);
2358 if (cgf.outermostConditional == this)
2359 cgf.outermostConditional = nullptr;
2360 }
2361
2362 /// Returns the insertion point which will be executed prior to each
2363 /// evaluation of the conditional code. In LLVM OG, this method
2364 /// is called getStartingBlock.
2365 mlir::OpBuilder::InsertPoint getInsertPoint() const { return insertPt; }
2366 };
2367
2369 std::optional<LValue> lhs{}, rhs{};
2370 mlir::Value result{};
2371 };
2372
2373 // Return true if we're currently emitting one branch or the other of a
2374 // conditional expression.
2375 bool isInConditionalBranch() const { return outermostConditional != nullptr; }
2376
2377 void setBeforeOutermostConditional(mlir::Value value, Address addr) {
2378 assert(isInConditionalBranch());
2379 {
2380 mlir::OpBuilder::InsertionGuard guard(builder);
2381 builder.restoreInsertionPoint(outermostConditional->getInsertPoint());
2382 builder.createStore(
2383 value.getLoc(), value, addr, /*isVolatile=*/false,
2384 /*isNontemporal=*/false,
2385 mlir::IntegerAttr::get(
2386 mlir::IntegerType::get(value.getContext(), 64),
2387 (uint64_t)addr.getAlignment().getAsAlign().value()));
2388 }
2389 }
2390
2391 // Points to the outermost active conditional control. This is used so that
2392 // we know if a temporary should be destroyed conditionally.
2394
2395 /// An RAII object to record that we're evaluating a statement
2396 /// expression.
2398 CIRGenFunction &cgf;
2399
2400 /// We have to save the outermost conditional: cleanups in a
2401 /// statement expression aren't conditional just because the
2402 /// StmtExpr is.
2403 ConditionalEvaluation *savedOutermostConditional;
2404
2405 public:
2407 : cgf(cgf), savedOutermostConditional(cgf.outermostConditional) {
2408 cgf.outermostConditional = nullptr;
2409 }
2410
2412 cgf.outermostConditional = savedOutermostConditional;
2413 }
2414 };
2415
2416 template <typename FuncTy>
2417 ConditionalInfo emitConditionalBlocks(const AbstractConditionalOperator *e,
2418 const FuncTy &branchGenFunc);
2419
2420 mlir::Value emitTernaryOnBoolExpr(const clang::Expr *cond, mlir::Location loc,
2421 const clang::Stmt *thenS,
2422 const clang::Stmt *elseS);
2423
2424 /// Build a "reference" to a va_list; this is either the address or the value
2425 /// of the expression, depending on how va_list is defined.
2426 Address emitVAListRef(const Expr *e);
2427
2428 /// Emits the start of a CIR variable-argument operation (`cir.va_start`)
2429 ///
2430 /// \param vaList A reference to the \c va_list as emitted by either
2431 /// \c emitVAListRef or \c emitMSVAListRef.
2432 void emitVAStart(mlir::Value vaList);
2433
2434 /// Emits the end of a CIR variable-argument operation (`cir.va_start`)
2435 ///
2436 /// \param vaList A reference to the \c va_list as emitted by either
2437 /// \c emitVAListRef or \c emitMSVAListRef.
2438 void emitVAEnd(mlir::Value vaList);
2439
2440 /// Generate code to get an argument from the passed in pointer
2441 /// and update it accordingly.
2442 ///
2443 /// \param ve The \c VAArgExpr for which to generate code.
2444 ///
2445 /// \param vaListAddr Receives a reference to the \c va_list as emitted by
2446 /// either \c emitVAListRef or \c emitMSVAListRef.
2447 ///
2448 /// \returns SSA value with the argument.
2449 mlir::Value emitVAArg(VAArgExpr *ve);
2450
2451 /// ----------------------
2452 /// CIR build helpers
2453 /// -----------------
2454public:
2455 cir::AllocaOp createTempAlloca(mlir::Type ty, mlir::Location loc,
2456 const Twine &name = "tmp",
2457 mlir::Value arraySize = nullptr,
2458 bool insertIntoFnEntryBlock = false);
2459 cir::AllocaOp createTempAlloca(mlir::Type ty, mlir::Location loc,
2460 const Twine &name = "tmp",
2461 mlir::OpBuilder::InsertPoint ip = {},
2462 mlir::Value arraySize = nullptr);
2463 Address createTempAlloca(mlir::Type ty, CharUnits align, mlir::Location loc,
2464 const Twine &name = "tmp",
2465 mlir::Value arraySize = nullptr,
2466 Address *alloca = nullptr,
2467 mlir::OpBuilder::InsertPoint ip = {});
2468 Address createTempAlloca(mlir::Type ty,
2469 mlir::ptr::MemorySpaceAttrInterface destAddrSpace,
2470 CharUnits align, mlir::Location loc,
2471 const Twine &name = "tmp",
2472 mlir::Value arraySize = nullptr,
2473 Address *alloca = nullptr,
2474 mlir::OpBuilder::InsertPoint ip = {});
2475 Address createTempAllocaWithoutCast(mlir::Type ty, CharUnits align,
2476 mlir::Location loc,
2477 const Twine &name = "tmp",
2478 mlir::Value arraySize = nullptr,
2479 mlir::OpBuilder::InsertPoint ip = {});
2480 Address
2481 maybeCastStackAddressSpace(Address alloca,
2482 mlir::ptr::MemorySpaceAttrInterface destAddrSpace,
2483 mlir::Value arraySize);
2484 Address createDefaultAlignTempAlloca(mlir::Type ty, mlir::Location loc,
2485 const Twine &name);
2486
2487 /// Create a temporary memory object of the given type, with
2488 /// appropriate alignmen and cast it to the default address space. Returns
2489 /// the original alloca instruction by \p Alloca if it is not nullptr.
2490 Address createMemTemp(QualType t, mlir::Location loc,
2491 const Twine &name = "tmp", Address *alloca = nullptr,
2492 mlir::OpBuilder::InsertPoint ip = {});
2493 Address createMemTemp(QualType t, CharUnits align, mlir::Location loc,
2494 const Twine &name = "tmp", Address *alloca = nullptr,
2495 mlir::OpBuilder::InsertPoint ip = {});
2496 Address createMemTempWithoutCast(QualType t, mlir::Location loc,
2497 const Twine &name = "tmp");
2498
2499 mlir::Value performAddrSpaceCast(mlir::Value v, mlir::Type destTy) const {
2500 if (cir::GlobalOp globalOp = v.getDefiningOp<cir::GlobalOp>())
2501 cgm.errorNYI("Global op addrspace cast");
2502 return builder.createAddrSpaceCast(v, destTy);
2503 }
2504
2505 //===--------------------------------------------------------------------===//
2506 // OpenMP Emission
2507 //===--------------------------------------------------------------------===//
2508public:
2509 mlir::LogicalResult emitOMPScopeDirective(const OMPScopeDirective &s);
2510 mlir::LogicalResult emitOMPErrorDirective(const OMPErrorDirective &s);
2511 mlir::LogicalResult emitOMPParallelDirective(const OMPParallelDirective &s);
2512 mlir::LogicalResult emitOMPTaskwaitDirective(const OMPTaskwaitDirective &s);
2513 mlir::LogicalResult emitOMPTaskyieldDirective(const OMPTaskyieldDirective &s);
2514 mlir::LogicalResult emitOMPBarrierDirective(const OMPBarrierDirective &s);
2515 mlir::LogicalResult emitOMPMetaDirective(const OMPMetaDirective &s);
2516 mlir::LogicalResult emitOMPCanonicalLoop(const OMPCanonicalLoop &s);
2517 mlir::LogicalResult emitOMPSimdDirective(const OMPSimdDirective &s);
2518 mlir::LogicalResult emitOMPTileDirective(const OMPTileDirective &s);
2519 mlir::LogicalResult emitOMPUnrollDirective(const OMPUnrollDirective &s);
2520 mlir::LogicalResult emitOMPFuseDirective(const OMPFuseDirective &s);
2521 mlir::LogicalResult emitOMPForDirective(const OMPForDirective &s);
2522 mlir::LogicalResult emitOMPForSimdDirective(const OMPForSimdDirective &s);
2523 mlir::LogicalResult emitOMPSectionsDirective(const OMPSectionsDirective &s);
2524 mlir::LogicalResult emitOMPSectionDirective(const OMPSectionDirective &s);
2525 mlir::LogicalResult emitOMPSingleDirective(const OMPSingleDirective &s);
2526 mlir::LogicalResult emitOMPMasterDirective(const OMPMasterDirective &s);
2527 mlir::LogicalResult emitOMPCriticalDirective(const OMPCriticalDirective &s);
2528 mlir::LogicalResult
2529 emitOMPParallelForDirective(const OMPParallelForDirective &s);
2530 mlir::LogicalResult
2531 emitOMPParallelForSimdDirective(const OMPParallelForSimdDirective &s);
2532 mlir::LogicalResult
2533 emitOMPParallelMasterDirective(const OMPParallelMasterDirective &s);
2534 mlir::LogicalResult
2535 emitOMPParallelSectionsDirective(const OMPParallelSectionsDirective &s);
2536 mlir::LogicalResult emitOMPTaskDirective(const OMPTaskDirective &s);
2537 mlir::LogicalResult emitOMPTaskgroupDirective(const OMPTaskgroupDirective &s);
2538 mlir::LogicalResult emitOMPFlushDirective(const OMPFlushDirective &s);
2539 mlir::LogicalResult emitOMPDepobjDirective(const OMPDepobjDirective &s);
2540 mlir::LogicalResult emitOMPScanDirective(const OMPScanDirective &s);
2541 mlir::LogicalResult emitOMPOrderedDirective(const OMPOrderedDirective &s);
2542 mlir::LogicalResult emitOMPAtomicDirective(const OMPAtomicDirective &s);
2543 mlir::LogicalResult emitOMPTargetDirective(const OMPTargetDirective &s);
2544 mlir::LogicalResult emitOMPTeamsDirective(const OMPTeamsDirective &s);
2545 mlir::LogicalResult
2547 mlir::LogicalResult emitOMPCancelDirective(const OMPCancelDirective &s);
2548 mlir::LogicalResult
2550 mlir::LogicalResult
2552 mlir::LogicalResult
2554 mlir::LogicalResult
2556 mlir::LogicalResult
2558 mlir::LogicalResult emitOMPTaskLoopDirective(const OMPTaskLoopDirective &s);
2559 mlir::LogicalResult
2561 mlir::LogicalResult
2563 mlir::LogicalResult
2565 mlir::LogicalResult
2567 mlir::LogicalResult
2569 mlir::LogicalResult
2571 mlir::LogicalResult
2572 emitOMPParallelMaskedDirective(const OMPParallelMaskedDirective &s);
2573 mlir::LogicalResult emitOMPParallelMaskedTaskLoopDirective(
2577 mlir::LogicalResult emitOMPParallelMasterTaskLoopDirective(
2581 mlir::LogicalResult
2583 mlir::LogicalResult emitOMPDistributeParallelForDirective(
2587 mlir::LogicalResult
2591 mlir::LogicalResult emitOMPTargetParallelForSimdDirective(
2593 mlir::LogicalResult
2595 mlir::LogicalResult emitOMPTargetTeamsGenericLoopDirective(
2597 mlir::LogicalResult
2599 mlir::LogicalResult
2601 mlir::LogicalResult
2607 mlir::LogicalResult
2609 mlir::LogicalResult
2611 mlir::LogicalResult emitOMPTargetTeamsDistributeDirective(
2619 mlir::LogicalResult emitOMPInteropDirective(const OMPInteropDirective &s);
2620 mlir::LogicalResult emitOMPDispatchDirective(const OMPDispatchDirective &s);
2621 mlir::LogicalResult
2623 mlir::LogicalResult emitOMPReverseDirective(const OMPReverseDirective &s);
2624 mlir::LogicalResult emitOMPSplitDirective(const OMPSplitDirective &s);
2625 mlir::LogicalResult
2627 mlir::LogicalResult emitOMPAssumeDirective(const OMPAssumeDirective &s);
2628 mlir::LogicalResult emitOMPMaskedDirective(const OMPMaskedDirective &s);
2629 mlir::LogicalResult emitOMPStripeDirective(const OMPStripeDirective &s);
2630
2634 void emitOMPAllocateDecl(const OMPAllocateDecl &d);
2637 void emitOMPRequiresDecl(const OMPRequiresDecl &d);
2638
2639 //===--------------------------------------------------------------------===//
2640 // OpenACC Emission
2641 //===--------------------------------------------------------------------===//
2642private:
2643 template <typename Op>
2644 Op emitOpenACCOp(mlir::Location start, OpenACCDirectiveKind dirKind,
2646 // Function to do the basic implementation of an operation with an Associated
2647 // Statement. Models AssociatedStmtConstruct.
2648 template <typename Op, typename TermOp>
2649 mlir::LogicalResult
2650 emitOpenACCOpAssociatedStmt(mlir::Location start, mlir::Location end,
2651 OpenACCDirectiveKind dirKind,
2653 const Stmt *associatedStmt);
2654
2655 template <typename Op, typename TermOp>
2656 mlir::LogicalResult emitOpenACCOpCombinedConstruct(
2657 mlir::Location start, mlir::Location end, OpenACCDirectiveKind dirKind,
2658 llvm::ArrayRef<const OpenACCClause *> clauses, const Stmt *loopStmt);
2659
2660 template <typename Op>
2661 void emitOpenACCClauses(Op &op, OpenACCDirectiveKind dirKind,
2663 // The second template argument doesn't need to be a template, since it should
2664 // always be an mlir::acc::LoopOp, but as this is a template anyway, we make
2665 // it a template argument as this way we can avoid including the OpenACC MLIR
2666 // headers here. We will count on linker failures/explicit instantiation to
2667 // ensure we don't mess this up, but it is only called from 1 place, and
2668 // instantiated 3x.
2669 template <typename ComputeOp, typename LoopOp>
2670 void emitOpenACCClauses(ComputeOp &op, LoopOp &loopOp,
2671 OpenACCDirectiveKind dirKind,
2673
2674 // The OpenACC LoopOp requires that we have auto, seq, or independent on all
2675 // LoopOp operations for the 'none' device type case. This function checks if
2676 // the LoopOp has one, else it updates it to have one.
2677 void updateLoopOpParallelism(mlir::acc::LoopOp &op, bool isOrphan,
2679
2680 // The OpenACC 'cache' construct actually applies to the 'loop' if present. So
2681 // keep track of the 'loop' so that we can add the cache vars to it correctly.
2682 mlir::acc::LoopOp *activeLoopOp = nullptr;
2683
2684 struct ActiveOpenACCLoopRAII {
2685 CIRGenFunction &cgf;
2686 mlir::acc::LoopOp *oldLoopOp;
2687
2688 ActiveOpenACCLoopRAII(CIRGenFunction &cgf, mlir::acc::LoopOp *newOp)
2689 : cgf(cgf), oldLoopOp(cgf.activeLoopOp) {
2690 cgf.activeLoopOp = newOp;
2691 }
2692 ~ActiveOpenACCLoopRAII() { cgf.activeLoopOp = oldLoopOp; }
2693 };
2694
2695 // Keep track of the last place we inserted a 'recipe' so that we can insert
2696 // the next one in lexical order.
2697 mlir::OpBuilder::InsertPoint lastRecipeLocation;
2698
2699public:
2700 // Helper type used to store the list of important information for a 'data'
2701 // clause variable, or a 'cache' variable reference.
2703 mlir::Location beginLoc;
2704 mlir::Value varValue;
2705 std::string name;
2706 // The type of the original variable reference: that is, after 'bounds' have
2707 // removed pointers/array types/etc. So in the case of int arr[5], and a
2708 // private(arr[1]), 'origType' is 'int', but 'baseType' is 'int[5]'.
2712 // The list of types that we found when going through the bounds, which we
2713 // can use to properly set the alloca section.
2715 };
2716
2717 // Gets the collection of info required to lower and OpenACC clause or cache
2718 // construct variable reference.
2720 // Helper function to emit the integer expressions as required by an OpenACC
2721 // clause/construct.
2722 mlir::Value emitOpenACCIntExpr(const Expr *intExpr);
2723 // Helper function to emit an integer constant as an mlir int type, used for
2724 // constants in OpenACC constructs/clauses.
2725 mlir::Value createOpenACCConstantInt(mlir::Location loc, unsigned width,
2726 int64_t value);
2727
2728 mlir::LogicalResult
2730 mlir::LogicalResult emitOpenACCLoopConstruct(const OpenACCLoopConstruct &s);
2731 mlir::LogicalResult
2733 mlir::LogicalResult emitOpenACCDataConstruct(const OpenACCDataConstruct &s);
2734 mlir::LogicalResult
2736 mlir::LogicalResult
2738 mlir::LogicalResult
2740 mlir::LogicalResult emitOpenACCWaitConstruct(const OpenACCWaitConstruct &s);
2741 mlir::LogicalResult emitOpenACCInitConstruct(const OpenACCInitConstruct &s);
2742 mlir::LogicalResult
2744 mlir::LogicalResult emitOpenACCSetConstruct(const OpenACCSetConstruct &s);
2745 mlir::LogicalResult
2747 mlir::LogicalResult
2749 mlir::LogicalResult emitOpenACCCacheConstruct(const OpenACCCacheConstruct &s);
2750
2753
2754 /// Create a temporary memory object for the given aggregate type.
2755 AggValueSlot createAggTemp(QualType ty, mlir::Location loc,
2756 const Twine &name = "tmp",
2757 Address *alloca = nullptr) {
2759 return AggValueSlot::forAddr(
2760 createMemTemp(ty, loc, name, alloca), ty.getQualifiers(),
2763 }
2764
2765private:
2766 QualType getVarArgType(const Expr *arg);
2767
2768 class InlinedInheritingConstructorScope {
2769 public:
2770 InlinedInheritingConstructorScope(CIRGenFunction &cgf, GlobalDecl gd)
2771 : cgf(cgf), oldCurGD(cgf.curGD), oldCurFuncDecl(cgf.curFuncDecl),
2772 oldCurCodeDecl(cgf.curCodeDecl),
2773 oldCxxabiThisDecl(cgf.cxxabiThisDecl),
2774 oldCxxThisValue(cgf.cxxThisValue),
2775 oldCxxabiThisAlignment(cgf.cxxabiThisAlignment),
2776 oldCxxThisAlignment(cgf.cxxThisAlignment),
2777 oldReturnValue(cgf.returnValue), oldFnRetTy(cgf.fnRetTy),
2778 oldCxxInheritedCtorInitExprArgs(
2779 std::move(cgf.cxxInheritedCtorInitExprArgs)) {
2780 cgf.curGD = gd;
2782 cgf.curCodeDecl = cgf.curFuncDecl;
2783 cgf.cxxabiThisDecl = nullptr;
2784 cgf.cxxabiThisValue = nullptr;
2785 cgf.cxxThisValue = nullptr;
2789 cgf.fnRetTy = QualType();
2790 cgf.cxxInheritedCtorInitExprArgs.clear();
2791 // FIXME: at one point when we want to call one of these, we'll need
2792 // CXXInheritedCtorInitExprArgs here too.
2793 }
2794 ~InlinedInheritingConstructorScope() {
2795 cgf.curGD = oldCurGD;
2796 cgf.curFuncDecl = oldCurFuncDecl;
2797 cgf.curCodeDecl = oldCurCodeDecl;
2798 cgf.cxxabiThisDecl = oldCxxabiThisDecl;
2799 cgf.cxxabiThisValue = oldCxxabiThisValue;
2800 cgf.cxxThisValue = oldCxxThisValue;
2801 cgf.cxxThisAlignment = oldCxxThisAlignment;
2802 cgf.cxxabiThisAlignment = oldCxxabiThisAlignment;
2803 cgf.returnValue = oldReturnValue;
2804 cgf.fnRetTy = oldFnRetTy;
2806 std::move(oldCxxInheritedCtorInitExprArgs);
2807 }
2808
2809 private:
2810 CIRGenFunction &cgf;
2811 GlobalDecl oldCurGD;
2812 const Decl *oldCurFuncDecl;
2813 const Decl *oldCurCodeDecl;
2814 ImplicitParamDecl *oldCxxabiThisDecl;
2815 mlir::Value oldCxxabiThisValue;
2816 mlir::Value oldCxxThisValue;
2817 clang::CharUnits oldCxxabiThisAlignment;
2818 clang::CharUnits oldCxxThisAlignment;
2819 Address oldReturnValue;
2820 QualType oldFnRetTy;
2821 CallArgList oldCxxInheritedCtorInitExprArgs;
2822 };
2823};
2824
2825} // namespace clang::CIRGen
2826
2827#endif
Defines the clang::ASTContext interface.
llvm::function_ref< void(mlir::OpBuilder &, mlir::Location)> BuilderCallbackRef
Definition CIRDialect.h:37
static void emitAtomicOp(CIRGenFunction &cgf, AtomicExpr *expr, Address dest, Address ptr, Address val1, Address val2, Expr *isWeakExpr, Expr *failureOrderExpr, int64_t size, cir::MemOrder order, cir::SyncScopeKind scope)
Defines the clang::Expr interface and subclasses for C++ expressions.
tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code, ArrayRef< tooling::Range > Ranges, StringRef FileName="<stdin>")
Clean up any erroneous/redundant code in the given Ranges in Code.
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
Defines an enumeration for C++ overloaded operators.
Enumerates target-specific builtins in their own namespaces within namespace clang.
C Language Family Type Representation.
This represents 'pragma omp cancel' directive.
This represents 'pragma omp cancellation point' directive.
This represents 'pragma omp dispatch' directive.
This represents 'pragma omp distribute' directive.
This represents 'pragma omp distribute parallel for' composite directive.
This represents 'pragma omp distribute parallel for simd' composite directive.
This represents 'pragma omp distribute simd' composite directive.
This represents 'pragma omp error' directive.
Represents the 'pragma omp fuse' loop transformation directive.
This represents 'pragma omp loop' directive.
Represents the 'pragma omp interchange' loop transformation directive.
This represents 'pragma omp interop' directive.
This represents 'pragma omp masked' directive.
This represents 'pragma omp masked taskloop' directive.
This represents 'pragma omp masked taskloop simd' directive.
This represents 'pragma omp master taskloop' directive.
This represents 'pragma omp master taskloop simd' directive.
This represents 'pragma omp metadirective' directive.
This represents 'pragma omp parallel loop' directive.
This represents 'pragma omp parallel masked taskloop' directive.
This represents 'pragma omp parallel masked taskloop simd' directive.
This represents 'pragma omp parallel master taskloop' directive.
This represents 'pragma omp parallel master taskloop simd' directive.
Represents the 'pragma omp reverse' loop transformation directive.
This represents 'pragma omp scan' directive.
Represents the 'pragma omp split' loop transformation directive.
This represents the 'pragma omp stripe' loop transformation directive.
This represents 'pragma omp target data' directive.
This represents 'pragma omp target' directive.
This represents 'pragma omp target enter data' directive.
This represents 'pragma omp target exit data' directive.
This represents 'pragma omp target parallel' directive.
This represents 'pragma omp target parallel for' directive.
This represents 'pragma omp target parallel for simd' directive.
This represents 'pragma omp target parallel loop' directive.
This represents 'pragma omp target simd' directive.
This represents 'pragma omp target teams' directive.
This represents 'pragma omp target teams distribute' combined directive.
This represents 'pragma omp target teams distribute parallel for' combined directive.
This represents 'pragma omp target teams distribute parallel for simd' combined directive.
This represents 'pragma omp target teams distribute simd' combined directive.
This represents 'pragma omp target teams loop' directive.
This represents 'pragma omp target update' directive.
This represents 'pragma omp taskloop' directive.
This represents 'pragma omp taskloop simd' directive.
This represents 'pragma omp teams' directive.
This represents 'pragma omp teams distribute' directive.
This represents 'pragma omp teams distribute parallel for' composite directive.
This represents 'pragma omp teams distribute parallel for simd' composite directive.
This represents 'pragma omp teams distribute simd' combined directive.
This represents 'pragma omp teams loop' directive.
This represents the 'pragma omp tile' loop transformation directive.
This represents the 'pragma omp unroll' loop transformation directive.
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:223
AbstractConditionalOperator - An abstract base class for ConditionalOperator and BinaryConditionalOpe...
Definition Expr.h:4359
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Definition Expr.h:2727
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition TypeBase.h:3821
AsmStmt is the base class for GCCAsmStmt and MSAsmStmt.
Definition Stmt.h:3287
AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*, __atomic_load,...
Definition Expr.h:6940
Represents an attribute applied to a statement.
Definition Stmt.h:2213
BinaryConditionalOperator - The GNU extension to the conditional operator which allows the middle ope...
Definition Expr.h:4459
OpaqueValueExpr * getOpaqueValue() const
getOpaqueValue - Return the opaque value placeholder.
Definition Expr.h:4497
Expr * getCommon() const
getCommon - Return the common expression, written to the left of the condition.
Definition Expr.h:4494
A builtin binary operation expression such as "x + y" or "x <= y".
Definition Expr.h:4044
BreakStmt - This represents a break.
Definition Stmt.h:3145
mlir::Value getPointer() const
Definition Address.h:98
static Address invalid()
Definition Address.h:76
clang::CharUnits getAlignment() const
Definition Address.h:138
mlir::Value getBasePointer() const
Definition Address.h:103
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.
cir::LoadOp createLoad(mlir::Location loc, Address addr, bool isVolatile=false, bool isNontemporal=false)
cir::StoreOp createStore(mlir::Location loc, mlir::Value val, Address dst, bool isVolatile=false, bool isNontemporal=false, mlir::IntegerAttr align={}, cir::SyncScopeKindAttr scope={}, cir::MemOrderAttr order={})
An abstract representation of regular/ObjC call/message targets.
AbstractCallee(const clang::FunctionDecl *fd)
const clang::ParmVarDecl * getParamDecl(unsigned I) const
ArrayInitLoopExprScope(CIRGenFunction &cgf, bool setIdx, mlir::Value index)
CIRGenFPOptionsRAII(CIRGenFunction &cgf, FPOptions FPFeatures)
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)
Captures the destructor cleanup for a loop's condition variable so that it can be emitted into the lo...
void emitIntoLoopCleanupRegion(mlir::Location loc)
Emit the captured condition-variable cleanups into the current insertion point (the loop's cleanup re...
FieldConstructionScope(CIRGenFunction &cgf, Address thisAddr)
FullExprCleanupScope(CIRGenFunction &cgf, const Expr *subExpr)
void exit(ArrayRef< mlir::Value * > valuesToReload={})
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...
Enters a new scope for capturing cleanups, all of which will be executed once the scope is exited.
RunCleanupsScope(CIRGenFunction &cgf)
Enter a new cleanup scope.
void forceLifetimeExtendedCleanups()
Promote any pending lifetime-extended cleanup entries onto the EH scope stack at the current insertio...
void forceCleanup(ArrayRef< mlir::Value * > valuesToReload={})
Force the emission of cleanups now, instead of waiting until this object is destroyed.
void forceCleanupExceptLifetimeExtended()
Force the emission of EH cleanups now, but defer promoting any lifetime-extended cleanup entries onto...
bool hasPendingCleanups() const
Whether there are any pending cleanups that have been pushed since this scope was entered.
~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...
cir::CallOp emitCoroEndBuiltinCall(mlir::Location loc, mlir::Value nullPtr)
static bool hasScalarEvaluationKind(clang::QualType type)
void emitFunctionProlog(const FunctionArgList &args, mlir::Block *entryBB, const FunctionDecl *fd, SourceLocation bodyBeginLoc)
Emit the function prologue: declare function arguments in the symbol table.
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,...
cir::CallOp emitCoroIDBuiltinCall(mlir::Location loc, mlir::Value nullPtr)
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::LogicalResult emitOMPTargetParallelForDirective(const OMPTargetParallelForDirective &s)
LValue emitCXXBindTemporaryLValue(const CXXBindTemporaryExpr *e)
mlir::LogicalResult emitOMPParallelMasterTaskLoopSimdDirective(const OMPParallelMasterTaskLoopSimdDirective &s)
void generateThunk(cir::FuncOp fn, const CIRGenFunctionInfo &fnInfo, GlobalDecl gd, const ThunkInfo &thunk, bool isUnprototyped)
Generate code for a thunk function.
mlir::LogicalResult emitOMPSimdDirective(const OMPSimdDirective &s)
mlir::Value emitCheckedArgForAssume(const Expr *e)
Emits an argument for a call to a __builtin_assume.
LValue emitOpaqueValueLValue(const OpaqueValueExpr *e)
mlir::LogicalResult emitDoStmt(const clang::DoStmt &s)
mlir::LogicalResult emitOMPCriticalDirective(const OMPCriticalDirective &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 emitCoreturnStmt(const CoreturnStmt &s)
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)
Address emitCXXMemberDataPointerAddress(const Expr *e, Address base, mlir::Value memberPtr, const MemberPointerType *memberPtrType, LValueBaseInfo *baseInfo)
bool curFuncIsThunk
In C++, whether we are code generating a thunk.
Address maybeCastStackAddressSpace(Address alloca, mlir::ptr::MemorySpaceAttrInterface destAddrSpace, mlir::Value arraySize)
mlir::LogicalResult emitOMPParallelMasterDirective(const OMPParallelMasterDirective &s)
mlir::LogicalResult emitOpenACCWaitConstruct(const OpenACCWaitConstruct &s)
cir::FuncOp generateCode(clang::GlobalDecl gd, cir::FuncOp fn, cir::FuncType funcType)
llvm::SmallVector< PendingCleanupEntry > lifetimeExtendedCleanupStack
mlir::LogicalResult emitOMPCancellationPointDirective(const OMPCancellationPointDirective &s)
mlir::LogicalResult emitOMPParallelMaskedTaskLoopDirective(const OMPParallelMaskedTaskLoopDirective &s)
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 initFullExprCleanup()
Set up the last cleanup that was pushed as a conditional full-expression cleanup.
void emitInvariantStart(CharUnits size, mlir::Value addr, mlir::Location loc)
Definition CIRGenCXX.cpp:33
mlir::LogicalResult emitOMPReverseDirective(const OMPReverseDirective &s)
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()
void emitLoopConditionCleanups(EHScopeStack::stable_iterator depth, mlir::Location loc)
Emit the cleanups captured for a loop's condition variable (those pushed above depth while EHScopeSta...
RValue emitCXXMemberCallExpr(const clang::CXXMemberCallExpr *e, ReturnValueSlot returnValue)
mlir::LogicalResult emitOpenACCUpdateConstruct(const OpenACCUpdateConstruct &s)
RValue emitCXXMemberPointerCallExpr(const CXXMemberCallExpr *ce, ReturnValueSlot returnValue)
LValue emitLValueForBitField(LValue base, const FieldDecl *field)
mlir::LogicalResult emitOMPTileDirective(const OMPTileDirective &s)
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.
void emitOMPRequiresDecl(const OMPRequiresDecl &d)
VlaSizePair getVLASize(const VariableArrayType *type)
Returns an MLIR::Value+QualType pair that corresponds to the size, in non-variably-sized elements,...
LValue emitScalarCompoundAssignWithComplex(const CompoundAssignOperator *e, mlir::Value &result)
mlir::LogicalResult emitOMPTargetTeamsDirective(const OMPTargetTeamsDirective &s)
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.
mlir::LogicalResult emitOMPTeamsDistributeParallelForDirective(const OMPTeamsDistributeParallelForDirective &s)
mlir::LogicalResult emitOMPBarrierDirective(const OMPBarrierDirective &s)
void setBeforeOutermostConditional(mlir::Value value, Address addr)
mlir::LogicalResult emitOMPTargetParallelDirective(const OMPTargetParallelDirective &s)
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)
const TargetInfo & getTarget() const
void replaceAddrOfLocalVar(const clang::VarDecl *vd, Address addr)
llvm::DenseMap< const clang::Decl *, Address > DeclMapTy
LValue emitConditionalOperatorLValue(const AbstractConditionalOperator *expr)
LValue emitLValue(const clang::Expr *e)
Emit code to compute a designator that specifies the location of the expression.
void addCatchHandlerAttr(const CXXCatchStmt *catchStmt, SmallVector< mlir::Attribute > &handlerAttrs)
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 emitOMPTargetDirective(const OMPTargetDirective &s)
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)
void emitInlinedInheritingCXXConstructorCall(SourceLocation loc, const CXXConstructorDecl *d, CXXCtorType ctorType, bool forVirtualBase, bool delegating, CallArgList &args)
Address getAddrOfLocalVar(const clang::VarDecl *vd)
Return the address of a local variable.
void emitAnyExprToExn(const Expr *e, Address addr)
void emitAggregateCopy(LValue dest, LValue src, QualType eltTy, AggValueSlot::Overlap_t mayOverlap, bool isVolatile=false)
Emit an aggregate copy.
LValue makeNaturalAlignAddrLValue(mlir::Value val, QualType ty)
llvm::DenseMap< const Expr *, mlir::Value > vlaSizeMap
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,...
mlir::Value emitNVPTXDevicePrintfCallExpr(const CallExpr *expr)
Emit a device-side printf call for NVPTX targets.
void emitMustTailThunk(GlobalDecl gd, mlir::Value adjustedThisPtr, cir::FuncOp callee)
Emit a musttail call for a thunk with a potentially different ABI.
void pushIrregularPartialArrayCleanup(mlir::Value arrayBegin, Address arrayEndPointer, QualType elementType, CharUnits elementAlign, Destroyer *destroyer)
Push an EH cleanup to destroy already-constructed elements of the given array.
Address getAsNaturalAddressOf(Address addr, QualType pointeeTy)
void pushCleanupAndDeferDeactivation(CleanupKind kind, As... a)
Push a cleanup and record it for deferred deactivation.
LValue emitComplexCompoundAssignmentLValue(const CompoundAssignOperator *e)
mlir::LogicalResult emitOMPScopeDirective(const OMPScopeDirective &s)
void emitBeginCatch(const CXXCatchStmt *catchStmt, mlir::Value ehToken)
Begins a catch statement by initializing the catch variable and calling __cxa_begin_catch.
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.
mlir::LogicalResult emitOMPDepobjDirective(const OMPDepobjDirective &s)
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 emitLoopConditionVariable(const clang::VarDecl &d, DeferredLoopConditionCleanup &condCleanup)
Emit a loop's condition-variable declaration.
void emitStoreThroughExtVectorComponentLValue(RValue src, LValue dst)
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)
void emitOMPDeclareReduction(const OMPDeclareReductionDecl &d)
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)
VlaSizePair getVLAElements1D(const VariableArrayType *vla)
Return the number of elements for a single dimension for the given array type.
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.
mlir::LogicalResult emitOMPDistributeParallelForSimdDirective(const OMPDistributeParallelForSimdDirective &s)
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.
void emitCXXGuardedInit(const VarDecl &varDecl, cir::GlobalOp globalOp, bool performInit)
Emit a guarded initializer for a static local variable.
mlir::LogicalResult emitOMPUnrollDirective(const OMPUnrollDirective &s)
cir::CallOp emitCoroFreeBuiltin(const CallExpr *e)
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 emitOMPTaskDirective(const OMPTaskDirective &s)
mlir::LogicalResult emitOpenACCSetConstruct(const OpenACCSetConstruct &s)
mlir::Value performAddrSpaceCast(mlir::Value v, mlir::Type destTy) const
RValue emitReferenceBindingToExpr(const Expr *e)
Emits a reference binding to the passed in expression.
mlir::LogicalResult emitOMPTeamsGenericLoopDirective(const OMPTeamsGenericLoopDirective &s)
llvm::SmallVector< DeferredDeactivateCleanup > deferredDeactivationCleanupStack
VPtrsVector getVTablePointers(const clang::CXXRecordDecl *vtableClass)
const TargetCIRGenInfo & getTargetHooks() const
mlir::LogicalResult emitOMPCanonicalLoop(const OMPCanonicalLoop &s)
mlir::LogicalResult emitSwitchStmt(const clang::SwitchStmt &s)
RValue emitCoyieldExpr(const CoyieldExpr &e, AggValueSlot aggSlot=AggValueSlot::ignored(), bool ignoreResult=false)
mlir::Value evaluateOrEmitBuiltinObjectSize(const clang::Expr *e, unsigned type, cir::IntType resType, mlir::Value emittedE, bool isDynamic)
mlir::LogicalResult emitOMPTeamsDirective(const OMPTeamsDirective &s)
std::optional< mlir::Value > emitRISCVBuiltinExpr(unsigned builtinID, const CallExpr *expr)
void pushDestroyAndDeferDeactivation(QualType::DestructionKind dtorKind, Address addr, QualType type)
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)
mlir::LogicalResult emitOMPMaskedTaskLoopDirective(const OMPMaskedTaskLoopDirective &s)
CleanupKind getCleanupKind(QualType::DestructionKind kind)
clang::CharUnits cxxabiThisAlignment
mlir::Value emitBuiltinObjectSize(const clang::Expr *e, unsigned type, cir::IntType resType, mlir::Value emittedE, bool isDynamic)
Returns a Value corresponding to the size of the given expression by emitting a cir....
mlir::Value makeBinaryAtomicValue(cir::AtomicFetchKind kind, const clang::CallExpr *expr, mlir::Type *originalArgType=nullptr, mlir::Value *emittedArgValue=nullptr, cir::MemOrder ordering=cir::MemOrder::SequentiallyConsistent)
Utility to insert an atomic instruction based on Intrinsic::ID and the expression node.
RValue emitCUDAKernelCallExpr(const CUDAKernelCallExpr *expr, ReturnValueSlot returnValue)
mlir::LogicalResult emitOMPFuseDirective(const OMPFuseDirective &s)
AggValueSlot::Overlap_t getOverlapForFieldInit(const FieldDecl *fd)
mlir::LogicalResult emitSimpleStmt(const clang::Stmt *s, bool useCurrentScope)
mlir::LogicalResult emitOMPSectionDirective(const OMPSectionDirective &s)
mlir::Block * indirectGotoBlock
IndirectBranch - The first time an indirect goto is seen we create a block reserved for the indirect ...
mlir::Operation * curFn
The current function or global initializer that is generated code for.
mlir::LogicalResult emitAsmStmt(const clang::AsmStmt &s)
std::pair< mlir::Value, mlir::Type > emitAsmInputLValue(const TargetInfo::ConstraintInfo &info, LValue inputValue, QualType inputType, std::string &constraintString, SourceLocation loc)
Address emitExtVectorElementLValue(LValue lv, mlir::Location loc)
Generates lvalue for partial ext_vector access.
mlir::LogicalResult emitOMPParallelForSimdDirective(const OMPParallelForSimdDirective &s)
void emitOMPAllocateDecl(const OMPAllocateDecl &d)
mlir::LogicalResult emitOMPDistributeParallelForDirective(const OMPDistributeParallelForDirective &s)
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...
Address getAddressOfDerivedClass(mlir::Location loc, Address baseAddr, const CXXRecordDecl *derived, llvm::iterator_range< CastExpr::path_const_iterator > path, bool nullCheckValue)
std::optional< mlir::Value > emitTargetBuiltinExpr(unsigned builtinID, const clang::CallExpr *e, ReturnValueSlot &returnValue)
CallArgList cxxInheritedCtorInitExprArgs
The values of function arguments to use when evaluating CXXInheritedCtorInitExprs within this context...
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)
void emitOMPDeclareMapper(const OMPDeclareMapperDecl &d)
mlir::LogicalResult emitOMPMasterTaskLoopSimdDirective(const OMPMasterTaskLoopSimdDirective &s)
EHScopeStack ehStack
Tracks function scope overall cleanup handling.
void enterDtorCleanups(const CXXDestructorDecl *dtor, CXXDtorType type)
Enter the cleanups necessary to complete the given phase of destruction for a destructor.
llvm::SmallVector< const ParmVarDecl * > fnArgs
Save Parameter Decl for coroutine.
mlir::Value emitUnPromotedValue(mlir::Value result, QualType unPromotionType)
mlir::LogicalResult emitSwitchBody(const clang::Stmt *s)
void startThunk(cir::FuncOp fn, GlobalDecl gd, const CIRGenFunctionInfo &fnInfo, bool isUnprototyped)
Start generating a thunk function.
RValue emitAtomicLoad(LValue lvalue, SourceLocation loc, AggValueSlot slot=AggValueSlot::ignored())
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.
llvm::SmallVector< PendingCleanupEntry > deferredConditionalCleanupStack
void emitNewArrayInitializer(const CXXNewExpr *e, QualType elementType, mlir::Type elementTy, Address beginPtr, mlir::Value numElements, mlir::Value allocSizeWithoutCookie)
mlir::LogicalResult emitOMPTaskwaitDirective(const OMPTaskwaitDirective &s)
mlir::LogicalResult emitOMPFlushDirective(const OMPFlushDirective &s)
mlir::LogicalResult emitOMPGenericLoopDirective(const OMPGenericLoopDirective &s)
mlir::LogicalResult emitOMPTargetUpdateDirective(const OMPTargetUpdateDirective &s)
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.
static int64_t getZExtIntValueFromConstOp(mlir::Value val)
Get zero-extended integer from a mlir::Value that is an int constant or a constant op.
mlir::LogicalResult emitOMPOrderedDirective(const OMPOrderedDirective &s)
mlir::LogicalResult emitOMPTargetParallelForSimdDirective(const OMPTargetParallelForSimdDirective &s)
mlir::LogicalResult emitOMPInterchangeDirective(const OMPInterchangeDirective &s)
RValue emitLoadOfExtVectorElementLValue(LValue lv)
mlir::Value emitCXXTypeidExpr(const CXXTypeidExpr *e)
mlir::LogicalResult emitOMPDispatchDirective(const OMPDispatchDirective &s)
mlir::Type convertTypeForMem(QualType t)
mlir::LogicalResult emitCXXTryStmt(const clang::CXXTryStmt &s, cxxTryBodyEmitter &bodyCallback)
clang::QualType buildFunctionArgList(clang::GlobalDecl gd, FunctionArgList &args)
mlir::LogicalResult emitOMPParallelDirective(const OMPParallelDirective &s)
cir::CallOp emitCoroAllocBuiltinCall(mlir::Location loc)
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)
mlir::Value emitComplexPrePostIncDec(const UnaryOperator *e, LValue lv)
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)
mlir::LogicalResult emitAttributedStmt(const AttributedStmt &s)
void emitCXXConstructExpr(const clang::CXXConstructExpr *e, AggValueSlot dest)
mlir::Value emitLoadOfComplex(LValue src, SourceLocation loc)
Load a complex number from the specified l-value.
mlir::LogicalResult emitOMPForSimdDirective(const OMPForSimdDirective &s)
LValue emitAggExprToLValue(const Expr *e)
mlir::LogicalResult emitOMPTaskLoopDirective(const OMPTaskLoopDirective &s)
void emitStoreOfScalar(mlir::Value value, Address addr, bool isVolatile, clang::QualType ty, LValueBaseInfo baseInfo, bool isInit=false, bool isNontemporal=false)
void pushDestroy(QualType::DestructionKind dtorKind, Address addr, QualType type)
Push the standard destructor for the given type as at least a normal cleanup.
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 emitSVEPredicateCast(mlir::Value pred, unsigned minNumElts, mlir::Location loc)
mlir::Value emitCXXNewExpr(const CXXNewExpr *e)
RValue getUndefRValue(clang::QualType ty)
Get an appropriate 'undef' rvalue for the given type.
bool getAArch64SVEProcessedOperands(unsigned builtinID, const CallExpr *expr, SmallVectorImpl< mlir::Value > &ops, clang::SVETypeFlags typeFlags)
Address returnValue
The temporary alloca to hold the return value.
LValue makeAddrLValue(Address addr, QualType ty, LValueBaseInfo baseInfo)
void emitCallAndReturnForThunk(cir::FuncOp callee, const ThunkInfo *thunk, bool isUnprototyped)
Emit the call and return for a thunk function.
static int64_t getSExtIntValueFromConstOp(mlir::Value val)
Get integer from a mlir::Value that is an int constant or a constant op.
mlir::Value getArrayInitIndex()
Get the index of the current ArrayInitLoopExpr, if any.
mlir::LogicalResult emitOMPTargetDataDirective(const OMPTargetDataDirective &s)
std::optional< mlir::Value > emitX86BuiltinExpr(unsigned builtinID, const CallExpr *expr)
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)
mlir::LogicalResult emitOMPTargetParallelGenericLoopDirective(const OMPTargetParallelGenericLoopDirective &s)
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.
LValue emitPointerToDataMemberBinaryExpr(const BinaryOperator *e)
mlir::LogicalResult emitOMPParallelMaskedDirective(const OMPParallelMaskedDirective &s)
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 emitOMPMaskedTaskLoopSimdDirective(const OMPMaskedTaskLoopSimdDirective &s)
mlir::LogicalResult emitOMPAtomicDirective(const OMPAtomicDirective &s)
mlir::LogicalResult emitOpenACCShutdownConstruct(const OpenACCShutdownConstruct &s)
mlir::LogicalResult emitFunctionBody(const clang::Stmt *body)
mlir::LogicalResult emitBreakStmt(const clang::BreakStmt &s)
void initFullExprCleanupWithFlag(Address activeFlag)
mlir::LogicalResult emitIndirectGotoStmt(const IndirectGotoStmt &s)
mlir::LogicalResult emitOMPTeamsDistributeParallelForSimdDirective(const OMPTeamsDistributeParallelForSimdDirective &s)
mlir::LogicalResult emitOMPTaskgroupDirective(const OMPTaskgroupDirective &s)
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
mlir::LogicalResult emitOMPParallelMaskedTaskLoopSimdDirective(const OMPParallelMaskedTaskLoopSimdDirective &s)
mlir::LogicalResult emitOMPTeamsDistributeDirective(const OMPTeamsDistributeDirective &s)
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)
Address createCleanupActiveFlag()
Create an active flag variable for use with conditional cleanups.
bool shouldEmitVTableTypeCheckedLoad(const CXXRecordDecl *rd)
Returns whether we should perform a type checked load when loading a virtual function for virtual cal...
bool hasVolatileMember(QualType t)
returns true if aggregate type has a volatile member.
RValue emitLoadOfBitfieldLValue(LValue lv, SourceLocation loc)
mlir::LogicalResult emitOMPInteropDirective(const OMPInteropDirective &s)
RValue emitCall(const CIRGenFunctionInfo &funcInfo, const CIRGenCallee &callee, ReturnValueSlot returnValue, const CallArgList &args, cir::CIRCallOpInterface *callOp, mlir::Location loc)
mlir::LogicalResult emitOMPErrorDirective(const OMPErrorDirective &s)
LValue emitComplexAssignmentLValue(const BinaryOperator *e)
mlir::LogicalResult emitOMPSingleDirective(const OMPSingleDirective &s)
void emitCallArg(CallArgList &args, const clang::Expr *e, clang::QualType argType)
clang::FieldDecl * lambdaThisCaptureField
void deactivateCleanupBlock(EHScopeStack::stable_iterator cleanup, mlir::Operation *dominatingIP)
Deactivates the given cleanup block.
mlir::LogicalResult emitContinueStmt(const clang::ContinueStmt &s)
const clang::Decl * curCodeDecl
This is the inner-most code context, which includes blocks.
mlir::LogicalResult emitOMPTaskyieldDirective(const OMPTaskyieldDirective &s)
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...
mlir::Value getAsNaturalPointerTo(Address addr, QualType pointeeType)
mlir::LogicalResult emitOMPTargetTeamsDistributeSimdDirective(const OMPTargetTeamsDistributeSimdDirective &s)
LValue emitCallExprLValue(const clang::CallExpr *e)
mlir::LogicalResult emitOMPScanDirective(const OMPScanDirective &s)
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.
RValue emitBuiltinWithOneOverloadedType(const CallExpr *e, llvm::StringRef intrinName, mlir::Type resultType={})
Emit a simple LLVM intrinsic that takes N scalar arguments.
mlir::LogicalResult emitOMPTargetEnterDataDirective(const OMPTargetEnterDataDirective &s)
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.
std::optional< mlir::Value > emitAMDGPUBuiltinExpr(unsigned builtinID, const CallExpr *expr)
Emit a call to an AMDGPU builtin function.
std::optional< mlir::Value > emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, ReturnValueSlot returnValue, llvm::Triple::ArchType arch)
void emitCXXTemporary(const CXXTemporary *temporary, QualType tempType, Address ptr)
Emits all the code to cause the given temporary to be cleaned up.
LValue emitStringLiteralLValue(const StringLiteral *e, llvm::StringRef name=".str")
mlir::LogicalResult emitOMPMasterTaskLoopDirective(const OMPMasterTaskLoopDirective &s)
void emitAtomicExprWithMemOrder(const Expr *memOrder, bool isStore, bool isLoad, bool isFence, llvm::function_ref< void(cir::MemOrder)> emitAtomicOp)
void maybeEmitDeferredVarDeclInit(const VarDecl *vd)
mlir::Value getUndefConstant(mlir::Location loc, mlir::Type cirTy)
Return a CIR constant for an undefined value of cirTy.
llvm::SmallDenseMap< const ParmVarDecl *, const ImplicitParamDecl * > sizeArguments
If a ParmVarDecl had the pass_object_size attribute, this will contain a mapping from said ParmVarDec...
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)
std::optional< mlir::Value > emitAArch64SMEBuiltinExpr(unsigned builtinID, const CallExpr *expr)
LValue emitLValueForField(LValue base, const clang::FieldDecl *field)
mlir::Value emitScalarExpr(const clang::Expr *e, bool ignoreResultAssign=false)
Emit the computation of the specified expression of scalar type.
void pushStackRestore(CleanupKind kind, Address spMem)
LValue emitPseudoObjectLValue(const PseudoObjectExpr *E)
mlir::LogicalResult emitIfStmt(const clang::IfStmt &s)
mlir::LogicalResult emitOMPForDirective(const OMPForDirective &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...
mlir::LogicalResult emitOMPMasterDirective(const OMPMasterDirective &s)
void popCleanupBlocks(EHScopeStack::stable_iterator oldCleanupStackDepth, ArrayRef< mlir::Value * > valuesToReload={})
Takes the old cleanup stack size and emits the cleanup blocks that have been added.
mlir::Value emitPromotedScalarExpr(const Expr *e, QualType promotionType)
AggValueSlot::Overlap_t getOverlapForReturnValue()
Determine whether a return value slot may overlap some other object.
bool needsEHCleanup(QualType::DestructionKind kind)
Determines whether an EH cleanup is required to destroy a type with the given destruction kind.
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)
mlir::LogicalResult emitOMPMetaDirective(const OMPMetaDirective &s)
mlir::LogicalResult emitOMPDistributeSimdDirective(const OMPDistributeSimdDirective &s)
CIRGenBuilderTy & getBuilder()
void emitVAStart(mlir::Value vaList)
Emits the start of a CIR variable-argument operation (cir.va_start)
bool didCallStackSave
Whether a cir.stacksave operation has been added.
void emitDecl(const clang::Decl &d, bool evaluateConditionDecl=false)
mlir::LogicalResult emitOMPParallelGenericLoopDirective(const OMPParallelGenericLoopDirective &s)
LValue emitBinaryOperatorLValue(const BinaryOperator *e)
mlir::Value emitOpenACCIntExpr(const Expr *intExpr)
mlir::LogicalResult emitOMPMaskedDirective(const OMPMaskedDirective &s)
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.
void emitNonNullArgCheck(RValue rv, QualType argType, SourceLocation argLoc, AbstractCallee ac, unsigned paramNum)
Create a check for a function parameter that may potentially be declared as non-null.
void pushPendingCleanupToEHStack(const PendingCleanupEntry &entry)
Promote a single pending cleanup entry onto the EH scope stack.
mlir::LogicalResult emitOMPSplitDirective(const OMPSplitDirective &s)
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.
llvm::DenseMap< const VarDecl *, mlir::Value > nrvoFlags
A mapping from NRVO variables to the flags used to indicate when the NRVO has been applied to this va...
unsigned counterRefTmp
Hold counters for incrementally naming temporaries.
mlir::MLIRContext & getMLIRContext()
mlir::LogicalResult emitOpenACCEnterDataConstruct(const OpenACCEnterDataConstruct &s)
Destroyer * getDestroyer(clang::QualType::DestructionKind kind)
mlir::Value emitRuntimeCall(mlir::Location loc, cir::FuncOp callee, llvm::ArrayRef< mlir::Value > args={}, mlir::NamedAttrList attrs={})
void Destroyer(CIRGenFunction &cgf, Address addr, QualType ty)
void emitDestructorBody(FunctionArgList &args)
Emits the body of the current destructor.
LValue emitInitListLValue(const InitListExpr *e)
mlir::Value arrayInitIndex
The current array initialization index when evaluating an ArrayInitIndexExpr within an ArrayInitLoopE...
void emitAtomicInit(Expr *init, LValue dest)
void popCleanupBlock(bool forDeactivation=false)
Pop a cleanup block from the stack.
LValue emitCastLValue(const CastExpr *e)
Casts are never lvalues unless that cast is to a reference type.
LValue emitCXXTypeidLValue(const CXXTypeidExpr *e)
mlir::LogicalResult emitOMPTargetExitDataDirective(const OMPTargetExitDataDirective &s)
mlir::Value emitLoadOfScalar(LValue lvalue, SourceLocation loc)
EmitLoadOfScalar - Load a scalar value from an address, taking care to appropriately convert from the...
mlir::Value emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv)
llvm::SmallVector< cir::BlockAddrInfoAttr > indirectGotoTargets
Labels whose address is taken in this function (via &&label, as either an operation or a constant ini...
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)
RValue emitPseudoObjectRValue(const PseudoObjectExpr *e, AggValueSlot slot=AggValueSlot::ignored())
LValue emitDeclRefLValue(const clang::DeclRefExpr *e)
mlir::LogicalResult emitOMPTargetTeamsDistributeParallelForDirective(const OMPTargetTeamsDistributeParallelForDirective &s)
void emitComplexExprIntoLValue(const Expr *e, LValue dest, bool isInit)
void pushEHDestroyIfNeeded(QualType::DestructionKind dtorKind, Address addr, QualType type)
pushEHDestroyIfNeeded - Push the standard destructor for the given type as an EH-only cleanup.
void emitOMPThreadPrivateDecl(const OMPThreadPrivateDecl &d)
std::optional< mlir::Value > emitNVPTXBuiltinExpr(unsigned builtinID, const CallExpr *expr)
Emit a call to an NVPTX builtin function.
void emitOMPGroupPrivateDecl(const OMPGroupPrivateDecl &d)
llvm::DenseMap< const clang::ValueDecl *, clang::FieldDecl * > lambdaCaptureFields
mlir::LogicalResult emitOMPParallelForDirective(const OMPParallelForDirective &s)
RValue emitCoawaitExpr(const CoawaitExpr &e, AggValueSlot aggSlot=AggValueSlot::ignored(), bool ignoreResult=false)
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)
mlir::LogicalResult emitOMPSectionsDirective(const OMPSectionsDirective &s)
LValue makeAddrLValue(Address addr, QualType ty, AlignmentSource source=AlignmentSource::Type)
int64_t getAccessedFieldNo(unsigned idx, mlir::ArrayAttr elts)
LValue emitPredefinedLValue(const PredefinedExpr *e)
mlir::LogicalResult emitOMPDistributeDirective(const OMPDistributeDirective &s)
RValue emitAnyExpr(const clang::Expr *e, AggValueSlot aggSlot=AggValueSlot::ignored(), bool ignoreResult=false)
Emit code to compute the specified expression which can have any type.
mlir::LogicalResult emitOMPTargetTeamsDistributeParallelForSimdDirective(const OMPTargetTeamsDistributeParallelForSimdDirective &s)
void emitCXXDestructorCall(const CXXDestructorDecl *dd, CXXDtorType type, bool forVirtualBase, bool delegating, Address thisAddr, QualType thisTy)
mlir::LogicalResult emitOMPTargetTeamsGenericLoopDirective(const OMPTargetTeamsGenericLoopDirective &s)
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)
mlir::LogicalResult emitOMPTeamsDistributeSimdDirective(const OMPTeamsDistributeSimdDirective &s)
llvm::DenseMap< const OpaqueValueExpr *, RValue > opaqueRValues
RValue emitNewOrDeleteBuiltinCall(const FunctionProtoType *type, const CallExpr *callExpr, OverloadedOperatorKind op)
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)
std::pair< mlir::Value, mlir::Type > emitAsmInput(const TargetInfo::ConstraintInfo &info, const Expr *inputExpr, std::string &constraintString)
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::LogicalResult emitOMPTaskLoopSimdDirective(const OMPTaskLoopSimdDirective &s)
void emitAtomicStore(RValue rvalue, LValue dest, bool isInit)
mlir::Value emitStoreThroughBitfieldLValue(RValue src, LValue dstresult)
llvm::DenseMap< const OpaqueValueExpr *, LValue > opaqueLValues
Keeps track of the current set of opaque value expressions.
const CIRGenFunctionInfo * curFnInfo
CIRGenFunction(CIRGenModule &cgm, CIRGenBuilderTy &builder, bool suppressNewContext=false)
std::optional< mlir::Location > currSrcLoc
Use to track source locations across nested visitor traversals.
void terminateStructuredRegionBody(mlir::Region &r, mlir::Location loc)
Address createMemTempWithoutCast(QualType t, mlir::Location loc, const Twine &name="tmp")
LValue emitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *e)
LValue emitExtVectorElementExpr(const ExtVectorElementExpr *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 emitInheritedCXXConstructorCall(const CXXConstructorDecl *d, bool forVirtualBase, Address thisAddr, bool inheritedFromVBase, const CXXInheritedCtorInitExpr *e)
void emitCXXDeleteExpr(const CXXDeleteExpr *e)
mlir::LogicalResult emitCoroutineBody(const CoroutineBodyStmt &s)
void pushCleanupAfterFullExpr(CleanupKind kind, Address addr, QualType type, Destroyer *destroyer)
Queue a cleanup to be pushed after finishing the current full-expression.
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)
std::optional< mlir::Value > emitAArch64SVEBuiltinExpr(unsigned builtinID, const CallExpr *expr)
cir::CallOp emitCoroBeginBuiltinCall(mlir::Location loc, mlir::Value coroframeAddr)
void emitOMPCapturedExpr(const OMPCapturedExprDecl &d)
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 ...
mlir::LogicalResult emitOMPParallelMasterTaskLoopDirective(const OMPParallelMasterTaskLoopDirective &s)
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 pushLifetimeExtendedDestroy(CleanupKind kind, Address addr, QualType type, Destroyer *destroyer, bool useEHCleanupForArray)
RValue getOrCreateOpaqueRValueMapping(const OpaqueValueExpr *e)
Given an opaque value expression, return its RValue mapping if it exists, otherwise create one.
mlir::LogicalResult emitOMPCancelDirective(const OMPCancelDirective &s)
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.
mlir::Value emitFromMemory(mlir::Value value, clang::QualType ty)
EmitFromMemory - Change a scalar value from its memory representation to its value representation.
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 emitOMPStripeDirective(const OMPStripeDirective &s)
mlir::LogicalResult emitOMPTargetTeamsDistributeDirective(const OMPTargetTeamsDistributeDirective &s)
mlir::LogicalResult emitCompoundStmtWithoutScope(const clang::CompoundStmt &s, Address *lastValue=nullptr, AggValueSlot slot=AggValueSlot::ignored())
mlir::LogicalResult emitOMPParallelSectionsDirective(const OMPParallelSectionsDirective &s)
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)
mlir::Value emitDynamicCast(Address thisAddr, const CXXDynamicCastExpr *dce)
void emitAggExpr(const clang::Expr *e, AggValueSlot slot)
mlir::Value emitScalarOrConstFoldImmArg(unsigned iceArguments, unsigned idx, const Expr *argExpr)
ConditionalInfo emitConditionalBlocks(const AbstractConditionalOperator *e, const FuncTy &branchGenFunc)
Address createDefaultAlignTempAlloca(mlir::Type ty, mlir::Location loc, const Twine &name)
CreateDefaultAlignTempAlloca - This creates an alloca with the default alignment of the corresponding...
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)
mlir::LogicalResult emitOMPTargetSimdDirective(const OMPTargetSimdDirective &s)
LValue emitCXXConstructLValue(const CXXConstructExpr *e)
void finishThunk()
Finish generating a thunk function.
mlir::LogicalResult emitOMPAssumeDirective(const OMPAssumeDirective &s)
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)
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:50
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:193
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
static RValue get(mlir::Value v)
Definition CIRGenValue.h:83
Contains the address where the return value of a function can be stored, and whether the address is v...
Definition CIRGenCall.h:260
Represents a call to a CUDA kernel function.
Definition ExprCXX.h:238
Represents binding an expression to a temporary.
Definition ExprCXX.h:1497
CXXCatchStmt - This represents a C++ catch block.
Definition StmtCXX.h:29
Represents a call to a C++ constructor.
Definition ExprCXX.h:1552
Represents a C++ constructor within a class.
Definition DeclCXX.h:2633
Represents a C++ base or member initializer.
Definition DeclCXX.h:2398
A default argument (C++ [dcl.fct.default]).
Definition ExprCXX.h:1274
A use of a default initializer in a constructor or in aggregate initialization.
Definition ExprCXX.h:1381
Represents a delete expression for memory deallocation and destructor calls, e.g.
Definition ExprCXX.h:2630
Represents a C++ destructor within a class.
Definition DeclCXX.h:2898
A C++ dynamic_cast expression (C++ [expr.dynamic.cast]).
Definition ExprCXX.h:485
CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for statement, represented as 'for (ra...
Definition StmtCXX.h:136
Represents a call to an inherited base class constructor from an inheriting constructor.
Definition ExprCXX.h:1755
Represents a call to a member function that may be written either with member call syntax (e....
Definition ExprCXX.h:183
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2145
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)".
Definition ExprCXX.h:2359
A call to an overloaded operator written using operator syntax.
Definition ExprCXX.h:85
Represents a C++ pseudo-destructor (C++ [expr.pseudo]).
Definition ExprCXX.h:2749
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
Represents a C++ temporary.
Definition ExprCXX.h:1463
A C++ throw-expression (C++ [except.throw]).
Definition ExprCXX.h:1212
CXXTryStmt - A C++ try block, including all handlers.
Definition StmtCXX.h:70
A C++ typeid expression (C++ [expr.typeid]), which gets the type_info that corresponds to the supplie...
Definition ExprCXX.h:852
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2949
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition Expr.h:3153
CaseStmt - Represent a case statement.
Definition Stmt.h:1930
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Definition Expr.h:3682
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:4306
CompoundLiteralExpr - [C99 6.5.2.5].
Definition Expr.h:3611
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition Stmt.h:1750
ContinueStmt - This represents a continue.
Definition Stmt.h:3129
Represents a 'co_return' statement in the C++ Coroutines TS.
Definition StmtCXX.h:474
Represents the body of a coroutine.
Definition StmtCXX.h:321
SourceLocExprScopeGuard(const Expr *DefaultExpr, CurrentSourceLocExprScope &Current)
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:1276
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition Stmt.h:1641
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
DoStmt - This represents a 'do/while' stmt.
Definition Stmt.h:2842
This represents one expression.
Definition Expr.h:112
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:283
QualType getType() const
Definition Expr.h:144
ExtVectorElementExpr - This represents access to specific elements of a vector, and may occur on the ...
Definition Expr.h:6622
Represents a member of a struct/union/class.
Definition Decl.h:3204
ForStmt - This represents a 'for (init;cond;inc)' stmt.
Definition Stmt.h:2898
Represents a function declaration or definition.
Definition Decl.h:2029
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5406
GlobalDecl - represents a global declaration.
Definition GlobalDecl.h:57
const Decl * getDecl() const
Definition GlobalDecl.h:106
GotoStmt - This represents a direct goto.
Definition Stmt.h:2979
IndirectGotoStmt - This represents an indirect goto.
Definition Stmt.h:3018
Describes an C or C++ initializer list.
Definition Expr.h:5314
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition Expr.h:3370
A pointer to member type per C++ 8.3.3 - Pointers to members.
Definition TypeBase.h:3752
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
This represents 'pragma omp allocate ...' directive.
Definition DeclOpenMP.h:536
Pseudo declaration for capturing expressions.
Definition DeclOpenMP.h:445
This represents 'pragma omp declare mapper ...' directive.
Definition DeclOpenMP.h:349
This represents 'pragma omp declare reduction ...' directive.
Definition DeclOpenMP.h:239
This represents 'pragma omp groupprivate ...' directive.
Definition DeclOpenMP.h:173
This represents 'pragma omp requires...' directive.
Definition DeclOpenMP.h:479
This represents 'pragma omp threadprivate ...' directive.
Definition DeclOpenMP.h:110
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:1184
Expr * getSourceExpr() const
The source expression of an opaque value expression is the expression which originally generated the ...
Definition Expr.h:1234
Represents a parameter to a function.
Definition Decl.h:1819
[C99 6.4.2.2] - A predefined identifier such as func.
Definition Expr.h:2011
PseudoObjectExpr - An expression which accesses a pseudo-object l-value.
Definition Expr.h:6816
A (possibly-)qualified type.
Definition TypeBase.h:938
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition TypeBase.h:8529
The collection of all-type qualifiers we support.
Definition TypeBase.h:332
Flags to identify the types for overloaded SVE builtins.
Encodes a location in the source.
A trivial tuple used to represent a source range.
Stmt - This represents one statement.
Definition Stmt.h:86
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:343
Exposes information about the current target.
Definition TargetInfo.h:227
Represents a declaration of a type.
Definition Decl.h:3557
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Definition Type.h:41
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition Expr.h:2250
Represents a call to the builtin function __builtin_va_arg.
Definition Expr.h:4963
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:932
Represents a C array with a specified size that is not an integer-constant-expression.
Definition TypeBase.h:4065
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.
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
@ NormalCleanup
Denotes a cleanup that should run when a scope is exited using normal control flow (falling off the e...
const internal::VariadicDynCastAllOfMatcher< Decl, VarDecl > varDecl
Matches variable declarations.
const internal::VariadicDynCastAllOfMatcher< Stmt, CallExpr > callExpr
Matches call expressions.
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.
@ Address
A pointer to a ValueDecl.
Definition Primitives.h:28
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
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
U cast(CodeGen::Address addr)
Definition Address.h:327
#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 addr
The address of the alloca for languages with explicit address space (e.g.
bool emittedAsOffload
True if the variable was emitted as an offload recipe, and thus doesn't have the same sort of alloca ...
bool isConstantAggregate
True if the variable is of aggregate type and has a constant initializer.
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.
std::unique_ptr< CGCoroData > data
CXXDefaultArgExprScope(CIRGenFunction &cfg, const CXXDefaultArgExpr *e)
Scope that deactivates all enclosed deferred cleanups on exit.
A cleanup that was pushed to the EH stack but whose deactivation is deferred until the enclosing Clea...
Represents a scope, including function bodies, compound statements, and the substatements of if/while...
llvm::ArrayRef< mlir::Block * > getRetBlocks()
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::Location getRetLoc(mlir::Block *b)
A cleanup entry that will be promoted onto the EH scope stack at a later point.
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
VlaSizePair(mlir::Value num, QualType ty)
virtual mlir::LogicalResult operator()(CIRGenFunction &cgf)=0
The this pointer adjustment as well as an optional return adjustment for a thunk.
Definition Thunk.h:157