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"
40#include "llvm/ADT/ScopedHashTable.h"
41#include "llvm/IR/Instructions.h"
42#include "llvm/IR/Intrinsics.h"
43
44namespace {
45class ScalarExprEmitter;
46} // namespace
47
48namespace mlir {
49namespace acc {
50class LoopOp;
51} // namespace acc
52} // namespace mlir
53
54namespace clang {
55class OutlinedFunctionDecl;
56class SYCLKernelCallStmt;
57} // namespace clang
58
59namespace clang::CIRGen {
60
61struct CGCoroData;
62
64public:
66
67private:
68 friend class ::ScalarExprEmitter;
69 /// The builder is a helper class to create IR inside a function. The
70 /// builder is stateful, in particular it keeps an "insertion point": this
71 /// is where the next operations will be introduced.
72 CIRGenBuilderTy &builder;
73
74 /// Saves the builder's constrained floating-point configuration on
75 /// construction and restores it on destruction. The builder is shared
76 /// across all functions in the module, so its constrained-FP state must be
77 /// scoped to each function's emission.
78 ///
79 /// Note that the similarly named CIRGenFunction::CIRGenFPOptionsRAII
80 /// intentionally avoids restoring the "isFPConstrained" state because that
81 /// state is function-wide, but this object does restore the state so that
82 /// any CIRGenFunction instance created while we are in the process of
83 /// emitting another function cannot corrupt the prior functions state.
84 struct ConstrainedFPRAII {
85 CIRGenBuilderTy &builder;
86 bool savedIsFPConstrained;
88 llvm::RoundingMode savedRounding;
89
90 explicit ConstrainedFPRAII(CIRGenBuilderTy &builder)
91 : builder(builder), savedIsFPConstrained(builder.getIsFPConstrained()),
92 savedExcept(builder.getDefaultConstrainedExcept()),
93 savedRounding(builder.getDefaultConstrainedRounding()) {}
94 ~ConstrainedFPRAII() {
95 builder.setIsFPConstrained(savedIsFPConstrained);
96 builder.setDefaultConstrainedExcept(savedExcept);
97 builder.setDefaultConstrainedRounding(savedRounding);
98 }
99 } constrainedFPState{builder};
100
101public:
102 /// The GlobalDecl for the current function being compiled or the global
103 /// variable currently being initialized.
105
107
108 /// The compiler-generated variable that holds the return value.
109 std::optional<mlir::Value> fnRetAlloca;
110
111 // Holds coroutine data if the current function is a coroutine. We use a
112 // wrapper to manage its lifetime, so that we don't have to define CGCoroData
113 // in this header.
114 struct CGCoroInfo {
115 std::unique_ptr<CGCoroData> data;
116 CGCoroInfo();
117 ~CGCoroInfo();
118 };
120
121 bool isCoroutine() const { return curCoro.data != nullptr; }
122
123 /// The temporary alloca to hold the return value. This is
124 /// invalid iff the function has no return value.
126
127 /// Tracks function scope overall cleanup handling.
129
130 typedef void Destroyer(CIRGenFunction &cgf, Address addr, QualType ty);
131
132 class CapturedCleanups;
133
134 /// A cleanup whose destructor call is not emitted where the cleanup is
135 /// registered. Used by the lifetime-extended cleanup stack, whose entries
136 /// are later promoted onto the EH scope stack, and by the deferred
137 /// conditional cleanup stack, whose entries are emitted directly into a
138 /// conditional scope's cleanup region.
139 ///
140 /// A valid \c activeFlag means the cleanup is conditional. The flag tracks
141 /// at run time whether the object has been constructed, and guards the
142 /// destructor call.
143 ///
144 /// Currently only DestroyObject cleanups use this. When other cleanup types
145 /// are needed (e.g., CallLifetimeEnd), this struct can be extended with a
146 /// std::variant of cleanup data types.
153 /// If set, the cleanup is captured by this owner instead of opening a
154 /// cir.cleanup.scope when it is pushed onto the EH stack.
156 };
157
159
160 /// Cleanups for temporaries constructed inside a conditional.
161 ///
162 /// Temporaries are destroyed in reverse order of construction at the end of
163 /// the full expression. A cleanup lives in the cleanup region of a
164 /// cir.cleanup.scope, and those scopes nest, so nesting is what encodes the
165 /// order.
166 ///
167 /// For an unconditionally constructed temporary, EHScopeStack::pushCleanup
168 /// opens a scope where the temporary is constructed and leaves the builder in
169 /// its body, so each later temporary nests one level deeper and is destroyed
170 /// first.
171 ///
172 /// For a temporary constructed inside a conditional, pushFullExprCleanup
173 /// records the cleanup on this stack, paired with an active flag that is
174 /// cleared ahead of the conditional and set once the object is constructed.
175 /// The destructor call is emitted guarded by that flag, so it runs only on
176 /// the paths that constructed the object.
177 ///
178 /// ConditionalEvaluation opens the region holding those calls where the
179 /// conditional begins, nesting it inside the scopes of earlier temporaries
180 /// and outside later ones. Its body stays open for the rest of the full
181 /// expression, so its cleanup region runs at the end of it.
182 /// FullExprCleanupScope::exit closes these innermost first, then pops the
183 /// enclosing EH-stack cleanups.
185
186 /// One record per cir.cleanup.scope opened by a ConditionalEvaluation, as
187 /// described above. These are bookkeeping owned by CIRGenFunction, not RAII
188 /// objects. The scope outlives the ConditionalEvaluation that opened it,
189 /// and the enclosing FullExprCleanupScope is what closes it.
191 cir::CleanupScopeOp scope;
192
193 /// The size of deferredConditionalCleanupStack when this scope was
194 /// opened. Every open conditional scope shares that one stack, so the
195 /// entries from this index onward are the ones deferred from inside this
196 /// conditional. They are emitted into this scope's cleanup region, in
197 /// reverse, when it is closed.
199 };
201
202 /// The cir.cleanup.scope of the innermost FullExprCleanupScope that
203 /// materialized one, or null. ConditionalEvaluation opens a conditional
204 /// cleanup scope only while this is set, since a FullExprCleanupScope is
205 /// what closes those scopes.
206 cir::CleanupScopeOp currentFullExprCleanupScope = nullptr;
207
208 /// Set by emitLoopConditionVariable while it emits the initializer of a loop
209 /// condition variable that lifetime-extends temporaries with a destructor.
210 /// The cleanups of the temporaries that \c extendingDecl extends are
211 /// captured by \c cleanups for the loop's cleanup region and guarded by
212 /// \c activeFlag, instead of opening cir.cleanup.scope operations around the
213 /// cir.condition.
220
221 /// A cleanup that was pushed to the EH stack but whose deactivation is
222 /// deferred until the enclosing CleanupDeactivationScope exits. Used to
223 /// protect partially-constructed aggregates (e.g. lambda captures) so that
224 /// already-initialized sub-objects are destroyed if a later initializer
225 /// throws, while avoiding double-destruction after full construction.
231
232 /// Scope that deactivates all enclosed deferred cleanups on exit.
233 /// Mirrors CodeGenFunction::CleanupDeactivationScope in classic codegen.
237 bool deactivated = false;
238
242
244 assert(!deactivated && "Deactivating already deactivated scope");
245 auto &stack = cgf.deferredDeactivationCleanupStack;
246 for (size_t i = stack.size(); i > oldDeactivateCleanupStackSize; i--) {
247 cgf.deactivateCleanupBlock(stack[i - 1].cleanup,
248 stack[i - 1].dominatingIP);
249 stack[i - 1].dominatingIP->erase();
250 }
251 stack.resize(oldDeactivateCleanupStackSize);
252 deactivated = true;
253 }
254
259 };
260
262
263 /// If a ParmVarDecl had the pass_object_size attribute, this will contain a
264 /// mapping from said ParmVarDecl to its implicit "object_size" parameter.
265 llvm::SmallDenseMap<const ParmVarDecl *, const ImplicitParamDecl *>
267
268 /// A mapping from NRVO variables to the flags used to indicate
269 /// when the NRVO has been applied to this variable.
270 llvm::DenseMap<const VarDecl *, mlir::Value> nrvoFlags;
271
272 llvm::DenseMap<const clang::ValueDecl *, clang::FieldDecl *>
275
276 /// CXXThisDecl - When generating code for a C++ member function,
277 /// this will hold the implicit 'this' declaration.
279 mlir::Value cxxabiThisValue = nullptr;
280 mlir::Value cxxThisValue = nullptr;
283
284 /// When generating code for a constructor or destructor, this will hold the
285 /// implicit argument (e.g. VTT).
288
289 /// The value of 'this' to sue when evaluating CXXDefaultInitExprs within this
290 /// expression.
292
293 /// The values of function arguments to use when evaluating
294 /// CXXInheritedCtorInitExprs within this context.
296
297 /// The current array initialization index when evaluating an
298 /// ArrayInitIndexExpr within an ArrayInitLoopExpr.
299 mlir::Value arrayInitIndex = nullptr;
300
301 // Holds the Decl for the current outermost non-closure context
302 const clang::Decl *curFuncDecl = nullptr;
303 /// This is the inner-most code context, which includes blocks.
304 const clang::Decl *curCodeDecl = nullptr;
307
308 /// The current function or global initializer that is generated code for.
309 /// This is usually a cir::FuncOp, but it can also be a cir::GlobalOp for
310 /// global initializers.
311 mlir::Operation *curFn = nullptr;
312
313 /// Save Parameter Decl for coroutine.
315
316 using DeclMapTy = llvm::DenseMap<const clang::Decl *, Address>;
317 /// This keeps track of the CIR allocas or globals for local C
318 /// declarations.
320
321 /// The type of the condition for the emitting switch statement.
323
324 clang::ASTContext &getContext() const { return cgm.getASTContext(); }
325
326 CIRGenBuilderTy &getBuilder() { return builder; }
327
329 const CIRGenModule &getCIRGenModule() const { return cgm; }
330
332 // We currently assume this isn't called for a global initializer.
333 auto fn = mlir::cast<cir::FuncOp>(curFn);
334 return &fn.getRegion().front();
335 }
336
337 /// Sanitizers enabled for this function.
339
341 public:
345
346 private:
347 void ConstructorHelper(clang::FPOptions FPFeatures);
348 CIRGenFunction &cgf;
349 clang::FPOptions oldFPFeatures;
351 llvm::RoundingMode oldRounding;
352 };
354
355 /// Convert the active Clang floating-point options to CIR fast-math flags.
356 cir::FastMathFlags getCurrentFastMathFlags() const;
357
358 /// Create a CIR fast-math attribute from the specified flags.
359 cir::FastMathFlagsAttr getFastMathFlagsAttr(cir::FastMathFlags fastMathFlags);
360
361 /// The symbol table maps a variable name to a value in the current scope.
362 /// Entering a function creates a new scope, and the function arguments are
363 /// added to the mapping. When the processing of a function is terminated,
364 /// the scope is destroyed and the mappings created in this scope are
365 /// dropped.
366 using SymTableTy = llvm::ScopedHashTable<const clang::Decl *, mlir::Value>;
368
369 /// Whether a cir.stacksave operation has been added. Used to avoid
370 /// inserting cir.stacksave for multiple VLAs in the same scope.
371 bool didCallStackSave = false;
372
373 /// Whether or not a Microsoft-style asm block has been processed within
374 /// this fuction. These can potentially set the return value.
375 bool sawAsmBlock = false;
376
377 /// In C++, whether we are code generating a thunk. This controls whether we
378 /// should emit cleanups.
379 bool curFuncIsThunk = false;
380
381 mlir::Type convertTypeForMem(QualType t);
382
383 mlir::Type convertType(clang::QualType t);
384 mlir::Type convertType(const TypeDecl *t) {
385 return convertType(getContext().getTypeDeclType(t));
386 }
387
388 /// Get integer from a mlir::Value that is an int constant or a constant op.
389 static int64_t getSExtIntValueFromConstOp(mlir::Value val) {
390 auto constOp = val.getDefiningOp<cir::ConstantOp>();
391 assert(constOp && "getSExtIntValueFromConstOp call with non ConstantOp");
392 return constOp.getIntValue().getSExtValue();
393 }
394
395 /// Get zero-extended integer from a mlir::Value that is an int constant or a
396 /// constant op.
397 static int64_t getZExtIntValueFromConstOp(mlir::Value val) {
398 auto constOp = val.getDefiningOp<cir::ConstantOp>();
399 assert(constOp && "getZExtIntValueFromConstOp call with non ConstantOp");
400 return constOp.getIntValue().getZExtValue();
401 }
402
403 /// Return the cir::TypeEvaluationKind of QualType \c type.
405
409
413
415 bool suppressNewContext = false);
417
418 CIRGenTypes &getTypes() const { return cgm.getTypes(); }
419
420 const TargetInfo &getTarget() const { return cgm.getTarget(); }
421 mlir::MLIRContext &getMLIRContext() { return cgm.getMLIRContext(); }
422
424 return cgm.getTargetCIRGenInfo();
425 }
426
427 // ---------------------
428 // Opaque value handling
429 // ---------------------
430
431 /// Keeps track of the current set of opaque value expressions.
432 llvm::DenseMap<const OpaqueValueExpr *, LValue> opaqueLValues;
433 llvm::DenseMap<const OpaqueValueExpr *, RValue> opaqueRValues;
434
435 // This keeps track of the associated size for each VLA type.
436 // We track this by the size expression rather than the type itself because
437 // in certain situations, like a const qualifier applied to an VLA typedef,
438 // multiple VLA types can share the same size expression.
439 // FIXME: Maybe this could be a stack of maps that is pushed/popped as we
440 // enter/leave scopes.
441 llvm::DenseMap<const Expr *, mlir::Value> vlaSizeMap;
442
443public:
444 /// A non-RAII class containing all the information about a bound
445 /// opaque value. OpaqueValueMapping, below, is a RAII wrapper for
446 /// this which makes individual mappings very simple; using this
447 /// class directly is useful when you have a variable number of
448 /// opaque values or don't want the RAII functionality for some
449 /// reason.
450 class OpaqueValueMappingData {
451 const OpaqueValueExpr *opaqueValue;
452 bool boundLValue;
453
454 OpaqueValueMappingData(const OpaqueValueExpr *ov, bool boundLValue)
455 : opaqueValue(ov), boundLValue(boundLValue) {}
456
457 public:
458 OpaqueValueMappingData() : opaqueValue(nullptr) {}
459
460 static bool shouldBindAsLValue(const Expr *expr) {
461 // gl-values should be bound as l-values for obvious reasons.
462 // Records should be bound as l-values because IR generation
463 // always keeps them in memory. Expressions of function type
464 // act exactly like l-values but are formally required to be
465 // r-values in C.
466 return expr->isGLValue() || expr->getType()->isFunctionType() ||
468 }
469
471 bind(CIRGenFunction &cgf, const OpaqueValueExpr *ov, const Expr *e) {
472 if (shouldBindAsLValue(ov))
473 return bind(cgf, ov, cgf.emitLValue(e));
474 return bind(cgf, ov, cgf.emitAnyExpr(e));
475 }
476
478 bind(CIRGenFunction &cgf, const OpaqueValueExpr *ov, const LValue &lv) {
479 assert(shouldBindAsLValue(ov));
480 cgf.opaqueLValues.insert(std::make_pair(ov, lv));
481 return OpaqueValueMappingData(ov, true);
482 }
483
485 bind(CIRGenFunction &cgf, const OpaqueValueExpr *ov, const RValue &rv) {
486 assert(!shouldBindAsLValue(ov));
487 cgf.opaqueRValues.insert(std::make_pair(ov, rv));
488
489 OpaqueValueMappingData data(ov, false);
490
491 // Work around an extremely aggressive peephole optimization in
492 // EmitScalarConversion which assumes that all other uses of a
493 // value are extant.
495 return data;
496 }
497
498 bool isValid() const { return opaqueValue != nullptr; }
499 void clear() { opaqueValue = nullptr; }
500
502 assert(opaqueValue && "no data to unbind!");
503
504 if (boundLValue) {
505 cgf.opaqueLValues.erase(opaqueValue);
506 } else {
507 cgf.opaqueRValues.erase(opaqueValue);
509 }
510 }
511 };
512
513 /// An RAII object to set (and then clear) a mapping for an OpaqueValueExpr.
515 CIRGenFunction &cgf;
517
518 public:
522
523 /// Build the opaque value mapping for the given conditional
524 /// operator if it's the GNU ?: extension. This is a common
525 /// enough pattern that the convenience operator is really
526 /// helpful.
527 ///
530 : cgf(cgf) {
531 if (mlir::isa<ConditionalOperator>(op))
532 // Leave Data empty.
533 return;
534
536 mlir::cast<BinaryConditionalOperator>(op);
538 e->getCommon());
539 }
540
541 /// Build the opaque value mapping for an OpaqueValueExpr whose source
542 /// expression is set to the expression the OVE represents.
544 : cgf(cgf) {
545 if (ov) {
546 assert(ov->getSourceExpr() && "wrong form of OpaqueValueMapping used "
547 "for OVE with no source expression");
548 data = OpaqueValueMappingData::bind(cgf, ov, ov->getSourceExpr());
549 }
550 }
551
553 LValue lvalue)
554 : cgf(cgf),
555 data(OpaqueValueMappingData::bind(cgf, opaqueValue, lvalue)) {}
556
558 RValue rvalue)
559 : cgf(cgf),
560 data(OpaqueValueMappingData::bind(cgf, opaqueValue, rvalue)) {}
561
562 void pop() {
563 data.unbind(cgf);
564 data.clear();
565 }
566
568 if (data.isValid())
569 data.unbind(cgf);
570 }
571 };
572
573private:
574 /// Declare a variable in the current scope, return success if the variable
575 /// wasn't declared yet.
576 void declare(mlir::Value addrVal, const clang::Decl *var, clang::QualType ty,
577 mlir::Location loc, clang::CharUnits alignment,
578 bool isParam = false);
579
580public:
581 mlir::Value createDummyValue(mlir::Location loc, clang::QualType qt);
582
583 void emitNullInitialization(mlir::Location loc, Address destPtr, QualType ty);
584
585private:
586 // Track current variable initialization (if there's one)
587 const clang::VarDecl *currVarDecl = nullptr;
588 class VarDeclContext {
590 const clang::VarDecl *oldVal = nullptr;
591
592 public:
593 VarDeclContext(CIRGenFunction &p, const VarDecl *value) : p(p) {
594 if (p.currVarDecl)
595 oldVal = p.currVarDecl;
596 p.currVarDecl = value;
597 }
598
599 /// Can be used to restore the state early, before the dtor
600 /// is run.
601 void restore() { p.currVarDecl = oldVal; }
602 ~VarDeclContext() { restore(); }
603 };
604
605public:
606 /// Use to track source locations across nested visitor traversals.
607 /// Always use a `SourceLocRAIIObject` to change currSrcLoc.
608 std::optional<SourceRange> currSrcLoc;
609
611 CIRGenFunction &cgf;
612 std::optional<SourceRange> oldLoc;
613
614 public:
616 if (cgf.currSrcLoc)
617 oldLoc = cgf.currSrcLoc;
618 cgf.currSrcLoc = value;
619 }
620
621 /// Can be used to restore the state early, before the dtor
622 /// is run.
623 void restore() { cgf.currSrcLoc = oldLoc; }
625 };
626
628 llvm::ScopedHashTableScope<const clang::Decl *, mlir::Value>;
629
630 /// Hold counters for incrementally naming temporaries
631 unsigned counterRefTmp = 0;
632 unsigned counterAggTmp = 0;
633 std::string getCounterRefTmpAsString();
634 std::string getCounterAggTmpAsString();
635
636 /// Helpers to convert Clang's SourceLocation to a MLIR Location.
637 mlir::Location getLoc(clang::SourceLocation srcLoc);
638 mlir::Location getLoc(clang::SourceRange srcLoc);
639 mlir::Location getLoc(mlir::Location lhs, mlir::Location rhs);
640
641 const clang::LangOptions &getLangOpts() const { return cgm.getLangOpts(); }
642
644 if (cgm.getCodeGenOpts().getFiniteLoops() ==
646 return false;
647
648 // C++11 and later guarantees that a thread eventually will do one of the
649 // following (C++11 [intro.multithread]p24 and C++17 [intro.progress]p1):
650 // - terminate,
651 // - make a call to a library I/O function,
652 // - perform an access through a volatile glvalue, or
653 // - perform a synchronization operation or an atomic operation.
654 //
655 // Hence each function is 'mustprogress' in C++11 or later.
656 return getLangOpts().CPlusPlus11;
657 }
658
659 // [C++26][intro.progress] (DR)
660 // The implementation may assume that any thread will eventually do one of
661 // the following:
662 // [...]
663 // - continue execution of a trivial infinite loop ([stmt.iter.general]).
664 //
665 // A trivial infinite loop with no side effects (e.g. `while (true) {}`)
666 // is therefore exempt from the forward-progress guarantee. If such a loop
667 // is found in a function that was speculatively marked 'mustprogress',
668 // that attribute must be removed: otherwise the optimizer would be
669 // licensed to assume the loop terminates and could delete it.
670 bool checkIfLoopMustProgress(const clang::Expr *controllingExpression,
671 bool hasEmptyBody) {
673 getLangOpts(), cgm.getCodeGenOpts(), getContext(),
674 controllingExpression, hasEmptyBody, [this] {
675 curFn->removeAttr(cir::CIRDialect::getMustProgressAttrName());
676 });
677 }
678
679 /// True if an insertion point is defined. If not, this indicates that the
680 /// current code being emitted is unreachable.
681 /// FIXME(cir): we need to inspect this and perhaps use a cleaner mechanism
682 /// since we don't yet force null insertion point to designate behavior (like
683 /// LLVM's codegen does) and we probably shouldn't.
684 bool haveInsertPoint() const {
685 return builder.getInsertionBlock() != nullptr;
686 }
687
688 /// True if code emitted at the builder's insertion point can be reached.
689 /// After emitting a terminator CIRGen opens a fresh block to continue in, so
690 /// the insertion block holds unreachable code whenever it is neither its
691 /// region's entry block nor the target of a branch.
693 mlir::Block *block = builder.getInsertionBlock();
694 return block && (block->isEntryBlock() || !block->hasNoPredecessors());
695 }
696
697 // Wrapper for function prototype sources. Wraps either a FunctionProtoType or
698 // an ObjCMethodDecl.
700 llvm::PointerUnion<const clang::FunctionProtoType *,
701 const clang::ObjCMethodDecl *>
703
706 };
707
709
712 RValue emitAtomicLoad(LValue lvalue, SourceLocation loc, cir::MemOrder order,
713 bool isVolatile = false,
715
716 /// An abstract representation of regular/ObjC call/message targets.
718 /// The function declaration of the callee.
719 [[maybe_unused]] const clang::Decl *calleeDecl;
720
721 public:
722 AbstractCallee() : calleeDecl(nullptr) {}
723 AbstractCallee(const clang::FunctionDecl *fd) : calleeDecl(fd) {}
724
725 bool hasFunctionDecl() const {
726 return llvm::isa_and_nonnull<clang::FunctionDecl>(calleeDecl);
727 }
728
729 const clang::Decl *getDecl() const { return calleeDecl; }
730
731 unsigned getNumParams() const {
732 if (const auto *fd = llvm::dyn_cast<clang::FunctionDecl>(calleeDecl))
733 return fd->getNumParams();
734 return llvm::cast<clang::ObjCMethodDecl>(calleeDecl)->param_size();
735 }
736
737 const clang::ParmVarDecl *getParamDecl(unsigned I) const {
738 if (const auto *fd = llvm::dyn_cast<clang::FunctionDecl>(calleeDecl))
739 return fd->getParamDecl(I);
740 return *(llvm::cast<clang::ObjCMethodDecl>(calleeDecl)->param_begin() +
741 I);
742 }
743 };
744
745 /// True if the current statement has noinline attribute.
747
748 /// True if the current statement has always_inline attribute.
750
751 // The CallExpr within the current statement that the musttail attribute
752 // applies to. nullptr if there is no 'musttail' on the current statement.
753 const CallExpr *mustTailCall = nullptr;
754
755 struct VlaSizePair {
756 mlir::Value numElts;
758
759 VlaSizePair(mlir::Value num, QualType ty) : numElts(num), type(ty) {}
760 };
761
762 /// Return the number of elements for a single dimension
763 /// for the given array type.
764 VlaSizePair getVLAElements1D(const VariableArrayType *vla);
765
766 /// Returns an MLIR::Value+QualType pair that corresponds to the size,
767 /// in non-variably-sized elements, of a variable length array type,
768 /// plus that largest non-variably-sized element type. Assumes that
769 /// the type has already been emitted with emitVariablyModifiedType.
770 VlaSizePair getVLASize(const VariableArrayType *type);
771 VlaSizePair getVLASize(QualType type);
772
774
778
779 void finishFunction(SourceLocation endLoc);
780
781 /// Determine whether the given initializer is trivial in the sense
782 /// that it requires no code to be generated.
783 bool isTrivialInitializer(const Expr *init);
784
785 /// If the specified expression does not fold to a constant, or if it does but
786 /// contains a label, return false. If it constant folds return true and set
787 /// the boolean result in Result.
788 bool constantFoldsToBool(const clang::Expr *cond, bool &resultBool,
789 bool allowLabels = false);
791 llvm::APSInt &resultInt,
792 bool allowLabels = false);
793
794 /// Return true if the statement contains a label in it. If
795 /// this statement is not executed normally, it not containing a label means
796 /// that we can just remove the code.
797 bool containsLabel(const clang::Stmt *s, bool ignoreCaseStmts = false);
798
799 Address emitExtVectorElementLValue(LValue lv, mlir::Location loc);
800
801 class ConstantEmission {
802 // Cannot use mlir::TypedAttr directly here because of bit availability.
803 llvm::PointerIntPair<mlir::Attribute, 1, bool> valueAndIsReference;
804 ConstantEmission(mlir::TypedAttr c, bool isReference)
805 : valueAndIsReference(c, isReference) {}
806
807 public:
809 static ConstantEmission forReference(mlir::TypedAttr c) {
810 return ConstantEmission(c, true);
811 }
812 static ConstantEmission forValue(mlir::TypedAttr c) {
813 return ConstantEmission(c, false);
814 }
815
816 explicit operator bool() const {
817 return valueAndIsReference.getOpaqueValue() != nullptr;
818 }
819
820 bool isReference() const { return valueAndIsReference.getInt(); }
822 assert(isReference());
823 cgf.cgm.errorNYI(refExpr->getSourceRange(),
824 "ConstantEmission::getReferenceLValue");
825 return {};
826 }
827
828 mlir::TypedAttr getValue() const {
829 assert(!isReference());
830 return mlir::cast<mlir::TypedAttr>(valueAndIsReference.getPointer());
831 }
832 };
833
834 ConstantEmission tryEmitAsConstant(const DeclRefExpr *refExpr);
835 ConstantEmission tryEmitAsConstant(const MemberExpr *me);
836
839 /// The address of the alloca for languages with explicit address space
840 /// (e.g. OpenCL) or alloca casted to generic pointer for address space
841 /// agnostic languages (e.g. C++). Invalid if the variable was emitted
842 /// as a global constant.
844
845 /// True if the variable is of aggregate type and has a constant
846 /// initializer.
848
849 /// True if the variable is a __block variable that is captured by an
850 /// escaping block.
851 bool isEscapingByRef = false;
852
853 /// True if the variable was emitted as an offload recipe, and thus doesn't
854 /// have the same sort of alloca initialization.
855 bool emittedAsOffload = false;
856
857 /// True if lifetime op should be used.
858 bool useLifetimeMarkers = false;
859
860 mlir::Value nrvoFlag{};
861
862 struct Invalid {};
864
867
869
870 bool wasEmittedAsGlobal() const { return !addr.isValid(); }
871
873
874 /// Returns the raw, allocated address, which is not necessarily
875 /// the address of the object itself. It is casted to default
876 /// address space for address space agnostic languages.
877 Address getAllocatedAddress() const { return addr; }
878
879 // Changes the stored address for the emission. This function should only
880 // be used in extreme cases, and isn't required to model normal AST
881 // initialization/variables.
883
884 /// Returns the address of the object within this declaration.
885 /// Note that this does not chase the forwarding pointer for
886 /// __block decls.
888 if (!isEscapingByRef)
889 return addr;
890
892 return Address::invalid();
893 }
894 };
895
896 /// Perform the usual unary conversions on the specified expression and
897 /// compare the result against zero, returning an Int1Ty value.
898 mlir::Value evaluateExprAsBool(const clang::Expr *e);
899
900 cir::GlobalOp addInitializerToStaticVarDecl(const VarDecl &d,
901 cir::GlobalOp gv,
902 cir::GetGlobalOp gvAddr);
903
904 /// Enter the cleanups necessary to complete the given phase of destruction
905 /// for a destructor. The end result should call destructors on members and
906 /// base classes in reverse order of their construction.
908
909 /// Return the pointer to pass to the operator delete of the given
910 /// destructor, converted to the type of its first parameter if needed.
911 mlir::Value loadThisForDtorDelete(const CXXDestructorDecl *dd);
912
913 /// Determines whether an EH cleanup is required to destroy a type
914 /// with the given destruction kind.
915 /// TODO(cir): could be shared with Clang LLVM codegen
917 switch (kind) {
919 return false;
923 return getLangOpts().Exceptions;
925 return getLangOpts().Exceptions &&
926 cgm.getCodeGenOpts().ObjCAutoRefCountExceptions;
927 }
928 llvm_unreachable("bad destruction kind");
929 }
930
934
936
937 /// Set the address of a local variable.
939 assert(!localDeclMap.count(vd) && "Decl already exists in LocalDeclMap!");
940 localDeclMap.insert({vd, addr});
941
942 // Add to the symbol table if not there already.
943 if (symbolTable.count(vd))
944 return;
945 symbolTable.insert(vd, addr.getPointer());
946 }
947
948 // Replaces the address of the local variable, if it exists. Else does the
949 // same thing as setAddrOfLocalVar.
951 localDeclMap.insert_or_assign(vd, addr);
952 }
953
954 // A class to allow reverting changes to a var-decl's registration to the
955 // localDeclMap. This is used in cases where things are being inserted into
956 // the variable list but don't follow normal lookup/search rules, like in
957 // OpenACC recipe generation.
959 CIRGenFunction &cgf;
960 const VarDecl *vd;
961 bool shouldDelete = false;
962 Address oldAddr = Address::invalid();
963
964 public:
966 : cgf(cgf), vd(vd) {
967 auto mapItr = cgf.localDeclMap.find(vd);
968
969 if (mapItr != cgf.localDeclMap.end())
970 oldAddr = mapItr->second;
971 else
972 shouldDelete = true;
973 }
974
976 if (shouldDelete)
977 cgf.localDeclMap.erase(vd);
978 else
979 cgf.localDeclMap.insert_or_assign(vd, oldAddr);
980 }
981 };
982
984
987
988 static bool
990
997
1000
1004 const clang::CXXRecordDecl *nearestVBase,
1005 clang::CharUnits offsetFromNearestVBase,
1006 bool baseIsNonVirtualPrimaryBase,
1007 const clang::CXXRecordDecl *vtableClass,
1008 VisitedVirtualBasesSetTy &vbases, VPtrsVector &vptrs);
1009 /// Return the Value of the vtable pointer member pointed to by thisAddr.
1010 mlir::Value getVTablePtr(mlir::Location loc, Address thisAddr,
1011 const clang::CXXRecordDecl *vtableClass);
1012
1013 /// Returns whether we should perform a type checked load when loading a
1014 /// virtual function for virtual calls to members of RD. This is generally
1015 /// true when both vcall CFI and whole-program-vtables are enabled.
1017
1018 /// Source location information about the default argument or member
1019 /// initializer expression we're evaluating, if any.
1023
1024 /// A scope within which we are constructing the fields of an object which
1025 /// might use a CXXDefaultInitExpr. This stashes away a 'this' value to use if
1026 /// we need to evaluate the CXXDefaultInitExpr within the evaluation.
1028 public:
1030 : cgf(cgf), oldCXXDefaultInitExprThis(cgf.cxxDefaultInitExprThis) {
1031 cgf.cxxDefaultInitExprThis = thisAddr;
1032 }
1034 cgf.cxxDefaultInitExprThis = oldCXXDefaultInitExprThis;
1035 }
1036
1037 private:
1038 CIRGenFunction &cgf;
1039 Address oldCXXDefaultInitExprThis;
1040 };
1041
1042 /// The scope of a CXXDefaultInitExpr. Within this scope, the value of 'this'
1043 /// is overridden to be the object under construction.
1045 public:
1050 cgf.cxxThisValue = cgf.cxxDefaultInitExprThis.getPointer();
1051 cgf.cxxThisAlignment = cgf.cxxDefaultInitExprThis.getAlignment();
1052 }
1054 cgf.cxxThisValue = oldCXXThisValue;
1055 cgf.cxxThisAlignment = oldCXXThisAlignment;
1056 }
1057
1058 public:
1060 mlir::Value oldCXXThisValue;
1063 };
1064
1069
1070 /// The scope of an ArrayInitLoopExpr. Within this scope, the value of the
1071 /// current loop index is overridden. In order to encourage re-use of existing
1072 /// array initialization, this uses a flag to determine if it is a 'no-op' or
1073 /// not.
1075 public:
1076 ArrayInitLoopExprScope(CIRGenFunction &cgf, bool setIdx, mlir::Value index)
1077 : cgf(cgf),
1078 oldArrayInitIndex(setIdx
1079 ? std::optional<mlir::Value>(cgf.arrayInitIndex)
1080 : std::nullopt) {
1081 if (setIdx)
1082 cgf.arrayInitIndex = index;
1083 }
1085 if (oldArrayInitIndex.has_value())
1086 cgf.arrayInitIndex = *oldArrayInitIndex;
1087 }
1088
1089 private:
1090 CIRGenFunction &cgf;
1091 std::optional<mlir::Value> oldArrayInitIndex;
1092 };
1093
1094 /// Get the index of the current ArrayInitLoopExpr, if any.
1095 mlir::Value getArrayInitIndex() { return arrayInitIndex; }
1096
1098 LValue makeNaturalAlignAddrLValue(mlir::Value val, QualType ty);
1099
1100 /// Construct an address with the natural alignment of T. If a pointer to T
1101 /// is expected to be signed, the pointer passed to this function must have
1102 /// been signed, and the returned Address will have the pointer authentication
1103 /// information needed to authenticate the signed pointer.
1105 CharUnits alignment,
1106 bool forPointeeType = false,
1107 LValueBaseInfo *baseInfo = nullptr) {
1108 if (alignment.isZero())
1109 alignment = cgm.getNaturalTypeAlignment(t, baseInfo);
1110 return Address(ptr, convertTypeForMem(t), alignment);
1111 }
1112
1114 Address value, const CXXRecordDecl *derived,
1115 llvm::iterator_range<CastExpr::path_const_iterator> path,
1116 bool nullCheckValue, SourceLocation loc);
1117
1119 mlir::Location loc, Address baseAddr, const CXXRecordDecl *derived,
1120 llvm::iterator_range<CastExpr::path_const_iterator> path,
1121 bool nullCheckValue);
1122
1123 /// Return the VTT parameter that should be passed to a base
1124 /// constructor/destructor with virtual bases.
1125 /// FIXME: VTTs are Itanium ABI-specific, so the definition should move
1126 /// to ItaniumCXXABI.cpp together with all the references to VTT.
1127 mlir::Value getVTTParameter(GlobalDecl gd, bool forVirtualBase,
1128 bool delegating);
1129
1132 return makeAddrLValue(addr, ty, LValueBaseInfo(source));
1133 }
1134
1136 return LValue::makeAddr(addr, ty, baseInfo);
1137 }
1138
1139 void initializeVTablePointers(mlir::Location loc,
1140 const clang::CXXRecordDecl *rd);
1141 void initializeVTablePointer(mlir::Location loc, const VPtr &vptr);
1142
1144
1145 /// Return the address of a local variable.
1147 auto it = localDeclMap.find(vd);
1148 assert(it != localDeclMap.end() &&
1149 "Invalid argument to getAddrOfLocalVar(), no decl!");
1150 return it->second;
1151 }
1152
1154 mlir::Type fieldType, unsigned index);
1155
1156 /// Given an opaque value expression, return its LValue mapping if it exists,
1157 /// otherwise create one.
1159
1160 /// Given an opaque value expression, return its RValue mapping if it exists,
1161 /// otherwise create one.
1163
1164 /// Load the value for 'this'. This function is only valid while generating
1165 /// code for an C++ member function.
1166 /// FIXME(cir): this should return a mlir::Value!
1167 mlir::Value loadCXXThis() {
1168 assert(cxxThisValue && "no 'this' value for this function");
1169 return cxxThisValue;
1170 }
1172
1173 /// Load the VTT parameter to base constructors/destructors have virtual
1174 /// bases. FIXME: Every place that calls LoadCXXVTT is something that needs to
1175 /// be abstracted properly.
1176 mlir::Value loadCXXVTT() {
1177 assert(cxxStructorImplicitParamValue && "no VTT value for this function");
1179 }
1180
1181 /// Convert the given pointer to a complete class to the given direct base.
1183 Address value,
1184 const CXXRecordDecl *derived,
1185 const CXXRecordDecl *base,
1186 bool baseIsVirtual);
1187
1188 /// Determine whether a return value slot may overlap some other object.
1190 // FIXME: Assuming no overlap here breaks guaranteed copy elision for base
1191 // class subobjects. These cases may need to be revisited depending on the
1192 // resolution of the relevant core issue.
1194 }
1195
1196 /// Determine whether a base class initialization may overlap some other
1197 /// object.
1199 const CXXRecordDecl *baseRD,
1200 bool isVirtual);
1201
1202 /// Return a CIR constant for an undefined value of \p cirTy.
1203 mlir::Value getUndefConstant(mlir::Location loc, mlir::Type cirTy);
1204
1205 /// Get an appropriate 'undef' rvalue for the given type.
1207
1208 cir::FuncOp generateCode(clang::GlobalDecl gd, cir::FuncOp fn,
1209 cir::FuncType funcType);
1210
1212 FunctionArgList &args);
1213
1214 /// Emit the function prologue: initialize the return value of an
1215 /// implicit-return-zero function and declare function arguments in the
1216 /// symbol table.
1217 void emitFunctionProlog(const FunctionArgList &args, mlir::Block *entryBB,
1218 const FunctionDecl *fd, SourceLocation bodyBeginLoc);
1219
1220 /// Emit code for the start of a function.
1221 /// \param loc The location to be associated with the function.
1222 /// \param startLoc The location of the function body.
1224 cir::FuncOp fn, cir::FuncType funcType,
1226 clang::SourceLocation startLoc);
1227
1228 /// Wrap the function body in a `cir.try` that enforces the exception
1229 /// specification of \p d: a filter handler for a dynamic specification
1230 /// (`throw(T...)` or pre-C++17 `throw()`), or a terminate handler for a
1231 /// specification that permits nothing to escape.
1232 void emitStartEHSpec(const clang::Decl *d);
1233
1234 /// Close the `cir.try` opened by emitStartEHSpec.
1235 void emitEndEHSpec(const clang::Decl *d);
1236
1237 /// returns true if aggregate type has a volatile member.
1239 if (const auto *rd = t->getAsRecordDecl())
1240 return rd->hasVolatileMember();
1241 return false;
1242 }
1243
1244 void addCatchHandlerAttr(const CXXCatchStmt *catchStmt,
1245 SmallVector<mlir::Attribute> &handlerAttrs);
1246
1247 /// The cleanup depth enclosing all the cleanups associated with the
1248 /// parameters.
1250
1251 /// The `cir.try` wrapping a function whose exception specification has to be
1252 /// enforced. Null when the current function needs no such wrapper.
1253 cir::TryOp ehSpecTryOp;
1254
1255 /// Whether the wrapper opened by emitStartEHSpec is a terminate scope, whose
1256 /// handler calls std::terminate() for any escaping exception, rather than the
1257 /// filter of a dynamic exception specification.
1259 return ehSpecTryOp &&
1260 mlir::isa<cir::CatchAllAttr>(ehSpecTryOp.getHandlerTypes()[0]);
1261 }
1262
1264
1265 /// Takes the old cleanup stack size and emits the cleanup blocks
1266 /// that have been added.
1267 void popCleanupBlocks(EHScopeStack::stable_iterator oldCleanupStackDepth,
1268 ArrayRef<mlir::Value *> valuesToReload = {});
1269
1270 /// Pops cleanup blocks until the given savepoint is reached, then adds the
1271 /// cleanups from the given savepoint in the lifetime-extended cleanups stack.
1272 void popCleanupBlocks(EHScopeStack::stable_iterator oldCleanupStackDepth,
1273 size_t oldLifetimeExtendedSize,
1274 ArrayRef<mlir::Value *> valuesToReload = {});
1275 void popCleanupBlock(bool forDeactivation = false);
1276
1277 /// Emit the captured cleanups (those pushed above \p depth while EHScopeStack
1278 /// was capturing cleanups) at the current insertion point, which must be
1279 /// inside the cleanup region of the op that owns them, and pop them off the
1280 /// EH stack. Every cleanup above \p depth must have been captured.
1281 void emitCapturedCleanups(EHScopeStack::stable_iterator depth,
1282 mlir::Location loc);
1283
1284 void terminateStructuredRegionBody(mlir::Region &r, mlir::Location loc);
1285
1286 /// Deactivates the given cleanup block. The block cannot be reactivated. Pops
1287 /// it if it's the top of the stack.
1288 ///
1289 /// \param DominatingIP - An instruction which is known to
1290 /// dominate the current IP (if set) and which lies along
1291 /// all paths of execution between the current IP and the
1292 /// the point at which the cleanup comes into scope.
1293 void deactivateCleanupBlock(EHScopeStack::stable_iterator cleanup,
1294 mlir::Operation *dominatingIP);
1295
1296 /// Create an active flag variable for use with conditional cleanups. The
1297 /// flag is initialized to false before the outermost conditional and set to
1298 /// true at the current insertion point (inside the conditional branch).
1299 Address createCleanupActiveFlag();
1300
1301 /// Set up the last cleanup that was pushed as a conditional
1302 /// full-expression cleanup.
1303 void initFullExprCleanup();
1304 void initFullExprCleanupWithFlag(Address activeFlag);
1305
1306 /// Promote a single pending cleanup entry onto the EH scope stack. If the
1307 /// entry has a valid activeFlag, the cleanup is configured as conditional.
1308 /// Defined in CIRGenDecl.cpp where the concrete cleanup types are visible.
1309 void pushPendingCleanupToEHStack(const PendingCleanupEntry &entry);
1310
1311 /// Push a cleanup to be run at the end of the current full-expression. Safe
1312 /// against the possibility that we're currently inside a
1313 /// conditionally-evaluated expression.
1314 template <class T, class... As>
1316 // Outside a conditional the EH stack opens a scope here.
1317 if (!isInConditionalBranch())
1318 return ehStack.pushCleanup<T>(kind, a...);
1319
1320 // Inside a conditional, record the cleanup for the scope that
1321 // ConditionalEvaluation opened where the conditional began, guarded by a
1322 // flag set only where the object is constructed.
1323 Address activeFlag = createCleanupActiveFlag();
1325 PendingCleanupEntry{kind, a..., activeFlag});
1326 }
1327
1328 /// Push a cleanup and record it for deferred deactivation. The cleanup will
1329 /// be deactivated when the enclosing CleanupDeactivationScope exits.
1330 template <class T, class... As>
1332 mlir::Location loc = builder.getUnknownLoc();
1333 mlir::Operation *dominatingIP = builder.getBool(false, loc).getOperation();
1334 ehStack.pushCleanup<T>(kind, a...);
1336 {ehStack.stable_begin(), dominatingIP});
1337 }
1338
1340 Address addr, QualType type);
1342 QualType type, Destroyer *destroyer,
1343 bool useEHCleanupForArray);
1344
1345 /// Queue a cleanup to be pushed after finishing the current full-expression.
1346 /// When the enclosing RunCleanupsScope exits, popCleanupBlocks promotes these
1347 /// entries onto the EH scope stack for the enclosing scope.
1349 Destroyer *destroyer) {
1350 lifetimeExtendedCleanupStack.push_back({kind, addr, type, destroyer});
1351 }
1352
1353 /// Enters a new scope for capturing cleanups, all of which
1354 /// will be executed once the scope is exited.
1355 class RunCleanupsScope {
1356 EHScopeStack::stable_iterator cleanupStackDepth, oldCleanupStackDepth;
1357 size_t lifetimeExtendedCleanupStackSize;
1358 CleanupDeactivationScope deactivateCleanups;
1359
1360 protected:
1363
1364 private:
1365 RunCleanupsScope(const RunCleanupsScope &) = delete;
1366 void operator=(const RunCleanupsScope &) = delete;
1367
1368 protected:
1370
1371 public:
1372 /// Enter a new cleanup scope.
1374 : deactivateCleanups(cgf), performCleanup(true), cgf(cgf) {
1375 cleanupStackDepth = cgf.ehStack.stable_begin();
1376 lifetimeExtendedCleanupStackSize =
1377 cgf.lifetimeExtendedCleanupStack.size();
1378 oldDidCallStackSave = cgf.didCallStackSave;
1379 cgf.didCallStackSave = false;
1380 oldCleanupStackDepth = cgf.currentCleanupStackDepth;
1381 cgf.currentCleanupStackDepth = cleanupStackDepth;
1382 }
1383
1384 /// Exit this cleanup scope, emitting any accumulated cleanups.
1386 if (performCleanup)
1387 forceCleanup();
1388 }
1389
1390 /// Force the emission of cleanups now, instead of waiting
1391 /// until this object is destroyed.
1392 void forceCleanup(ArrayRef<mlir::Value *> valuesToReload = {}) {
1393 assert(performCleanup && "Already forced cleanup");
1395
1396 // forceDeactivate() can pop cleanup scopes that were pushed with
1397 // deferred deactivation, which moves the insertion point out of the
1398 // cleanup body region. Any caller value defined inside such a body
1399 // would no longer dominate uses past the scope. The downstream
1400 // popCleanupBlocks() handles the spill for any cleanups it pops
1401 // itself, but it cannot help with cleanups that forceDeactivate has
1402 // already popped. Spill those values here, while the insertion point
1403 // is still inside the body, so we can reload them after all popping
1404 // is done. We only spill values whose defining op lives inside a
1405 // cir.cleanup.scope, since values defined outside any cleanup scope
1406 // (e.g. allocas in the entry block) already dominate the post-scope
1407 // insertion point.
1408 const bool hasPendingDeactivations =
1410 deactivateCleanups.oldDeactivateCleanupStackSize;
1411
1412 llvm::SmallVector<Address> tempAllocas;
1413 bool didSpillAny = false;
1414 if (hasPendingDeactivations) {
1415 tempAllocas.reserve(valuesToReload.size());
1416 for (mlir::Value *valPtr : valuesToReload) {
1417 mlir::Value val = *valPtr;
1418 if (!val || !val.getDefiningOp() ||
1419 !val.getDefiningOp()->getParentOfType<cir::CleanupScopeOp>()) {
1420 tempAllocas.push_back(Address::invalid());
1421 continue;
1422 }
1424 val.getType(), val.getLoc(), "tmp.exprcleanup");
1425 tempAllocas.push_back(temp);
1426 cgf.builder.createStore(val.getLoc(), val, temp);
1427 didSpillAny = true;
1428 }
1429 }
1430
1431 deactivateCleanups.forceDeactivate();
1432 // If we already spilled some of the caller's values, don't ask
1433 // popCleanupBlocks to spill them again. Values we did not pre-spill
1434 // are not inside any cir.cleanup.scope, so they cannot be invalidated
1435 // by either forceDeactivate's or popCleanupBlocks's pops (both only
1436 // pop cir.cleanup.scope ops); they already dominate the post-scope
1437 // insertion point on their own.
1438 if (didSpillAny) {
1439 cgf.popCleanupBlocks(cleanupStackDepth,
1440 lifetimeExtendedCleanupStackSize);
1441
1442 // Reload the spilled values now that all cleanup popping (and
1443 // promotion of any lifetime-extended cleanups onto the EH stack) is
1444 // done.
1445 for (auto [addr, valPtr] : llvm::zip(tempAllocas, valuesToReload)) {
1446 if (!addr.isValid())
1447 continue;
1448 *valPtr = cgf.builder.createLoad(valPtr->getLoc(), addr);
1449 }
1450 } else {
1451 cgf.popCleanupBlocks(cleanupStackDepth,
1452 lifetimeExtendedCleanupStackSize, valuesToReload);
1453 }
1454
1455 performCleanup = false;
1456 cgf.currentCleanupStackDepth = oldCleanupStackDepth;
1457 }
1458
1459 /// Force the emission of EH cleanups now, but defer promoting any
1460 /// lifetime-extended cleanup entries onto the EH scope stack. The caller
1461 /// must subsequently call forceLifetimeExtendedCleanups() to finalize the
1462 /// scope.
1464 assert(performCleanup && "Already forced cleanup");
1465 cgf.didCallStackSave = oldDidCallStackSave;
1466 deactivateCleanups.forceDeactivate();
1467 cgf.popCleanupBlocks(cleanupStackDepth);
1468 }
1469
1470 /// Promote any pending lifetime-extended cleanup entries onto the EH scope
1471 /// stack at the current insertion point and finalize this scope. This must
1472 /// be paired with a prior call to forceCleanupExceptLifetimeExtended().
1474 assert(performCleanup && "Already forced cleanup");
1475 assert(deactivateCleanups.deactivated &&
1476 "forceCleanupExceptLifetimeExtended() must be called first");
1477 cgf.popCleanupBlocks(cleanupStackDepth, lifetimeExtendedCleanupStackSize);
1478 performCleanup = false;
1479 cgf.currentCleanupStackDepth = oldCleanupStackDepth;
1480 }
1481
1482 /// Whether there are any pending cleanups that have been pushed since
1483 /// this scope was entered.
1484 bool hasPendingCleanups() const {
1485 return cgf.ehStack.stable_begin() != cleanupStackDepth;
1486 }
1487 };
1488
1489 // Cleanup stack depth of the RunCleanupsScope that was pushed most recently.
1491
1493 CIRGenFunction &cgf;
1494 RunCleanupsScope cleanups;
1495 cir::CleanupScopeOp scope;
1496 cir::CleanupScopeOp oldFullExprCleanupScope;
1497 size_t deferredCleanupStackSize;
1498 size_t conditionalScopeDepth;
1499 bool exited = false;
1500
1501 public:
1502 FullExprCleanupScope(CIRGenFunction &cgf, const Expr *subExpr);
1503
1504 void exit(ArrayRef<mlir::Value *> valuesToReload = {});
1505
1507 if (!exited)
1508 exit();
1509 }
1510
1511 private:
1513 void operator=(const FullExprCleanupScope &) = delete;
1514 };
1515
1516 /// Captures cleanups for variables whose lifetime ends in a region owned by
1517 /// an enclosing op rather than at the end of a cir.cleanup.scope, so that
1518 /// they can be emitted into that region later. Examples for uses are:
1519 /// * A loop condition variable's cleanups in the loop op's per-iteration
1520 /// cleanup region.
1521 /// * Coroutine parameters and promises, which are cleaned up in a separate
1522 /// destroy region
1524 CIRGenFunction &cgf;
1526 bool active;
1527
1528 public:
1530 : cgf(cgf), depth(cgf.ehStack.stable_begin()), active(active) {}
1531
1532 /// An RAII class that suppresses cir.cleanup.scope creation for cleanups
1533 /// pushed onto the EH stack while such a variable is being emitted and
1534 /// instead captures these cleanups so that they can be emitted into the
1535 /// owning op's cleanup region later.
1537 EHScopeStack &ehStack;
1538
1539 public:
1541 : ehStack(scope.cgf.ehStack) {
1542 // Capture scopes deliberately wrap individual cleanup-producing
1543 // operations, so they must never nest.
1544 assert(!ehStack.isCapturingCleanups() &&
1545 "cleanup capturing should not nest");
1546 if (scope.active)
1547 ehStack.setCapturingCleanups(true);
1548 }
1549 ~CaptureScope() { ehStack.setCapturingCleanups(false); }
1550
1551 CaptureScope(const CaptureScope &) = delete;
1552 void operator=(const CaptureScope &) = delete;
1553 };
1554
1555 /// Emit the captured cleanups into the current insertion point, which must
1556 /// be inside the owning op's cleanup region.
1557 void emitIntoCleanupRegion(mlir::Location loc) {
1558 if (active)
1559 cgf.emitCapturedCleanups(depth, loc);
1560 }
1561
1562 private:
1563 CapturedCleanups(const CapturedCleanups &) = delete;
1564 void operator=(const CapturedCleanups &) = delete;
1565 };
1566
1567public:
1568 /// Represents a scope, including function bodies, compound statements, and
1569 /// the substatements of if/while/do/for/switch/try statements. This class
1570 /// handles any automatic cleanup, along with the return value.
1571 struct LexicalScope : public RunCleanupsScope {
1572 private:
1573 // Points to the scope entry block. This is useful, for instance, for
1574 // helping to insert allocas before finalizing any recursive CodeGen from
1575 // switches.
1576 mlir::Block *entryBlock;
1577
1578 LexicalScope *parentScope = nullptr;
1579
1580 // Holds the actual value for ScopeKind::Try
1581 cir::TryOp tryOp = nullptr;
1582
1583 // On a coroutine body, the OnFallthrough sub stmt holds the handler
1584 // (CoreturnStmt) for control flow falling off the body. Keep track
1585 // of a co_return emitted in this scope and not followed by a label, and
1586 // allow OnFallthrough to be skipped.
1587 bool hasCoreturnSinceLastLabel = false;
1588
1589 // Only Regular is used at the moment. Support for other kinds will be
1590 // added as the relevant statements/expressions are upstreamed.
1591 enum Kind {
1592 Regular, // cir.if, cir.scope, if_regions
1593 Ternary, // cir.ternary
1594 Switch, // cir.switch
1595 Try, // cir.try
1596 GlobalInit // cir.global initialization code
1597 };
1598 Kind scopeKind = Kind::Regular;
1599
1600 // The scope return value.
1601 mlir::Value retVal = nullptr;
1602
1603 mlir::Location beginLoc;
1604 mlir::Location endLoc;
1605
1606 public:
1607 unsigned depth = 0;
1608
1609 LexicalScope(CIRGenFunction &cgf, mlir::Location loc, mlir::Block *eb)
1610 : RunCleanupsScope(cgf), entryBlock(eb), parentScope(cgf.curLexScope),
1611 beginLoc(loc), endLoc(loc) {
1612
1613 assert(entryBlock && "LexicalScope requires an entry block");
1614 cgf.curLexScope = this;
1615 if (parentScope)
1616 ++depth;
1617
1618 if (const auto fusedLoc = mlir::dyn_cast<mlir::FusedLoc>(loc)) {
1619 assert(fusedLoc.getLocations().size() == 2 && "too many locations");
1620 beginLoc = fusedLoc.getLocations()[0];
1621 endLoc = fusedLoc.getLocations()[1];
1622 }
1623 }
1624
1625 void setRetVal(mlir::Value v) { retVal = v; }
1626
1627 void cleanup();
1628 void restore() { cgf.curLexScope = parentScope; }
1629
1632 cleanup();
1633 restore();
1634 }
1635
1636 // ---
1637 // Coroutine tracking
1638 // ---
1639 bool hasCoreturn() const { return hasCoreturnSinceLastLabel; }
1640 // Record an emitted co_return for fallthrough tracking.
1641 // A later label clears this state.
1642 void markCoreturnEmitted() { hasCoreturnSinceLastLabel = true; }
1643 // A goto can reach a label after a co_return, and the code after it, so
1644 // the end of this scope and of the enclosing ones may be reachable again.
1646 for (LexicalScope *s = this; s; s = s->parentScope)
1647 s->hasCoreturnSinceLastLabel = false;
1648 }
1649
1650 // ---
1651 // Kind
1652 // ---
1653 bool isGlobalInit() { return scopeKind == Kind::GlobalInit; }
1654 bool isRegular() { return scopeKind == Kind::Regular; }
1655 bool isSwitch() { return scopeKind == Kind::Switch; }
1656 bool isTernary() { return scopeKind == Kind::Ternary; }
1657 bool isTry() { return scopeKind == Kind::Try; }
1658 cir::TryOp getClosestTryParent();
1659 void setAsGlobalInit() { scopeKind = Kind::GlobalInit; }
1660 void setAsSwitch() { scopeKind = Kind::Switch; }
1661 void setAsTernary() { scopeKind = Kind::Ternary; }
1662 void setAsTry(cir::TryOp op) {
1663 scopeKind = Kind::Try;
1664 tryOp = op;
1665 }
1666
1667 cir::TryOp getTry() {
1668 assert(isTry());
1669 return tryOp;
1670 }
1671
1672 // ---
1673 // Return handling.
1674 // ---
1675
1676 private:
1677 // On switches we need one return block per region, since cases don't
1678 // have their own scopes but are distinct regions nonetheless.
1679
1680 // TODO: This implementation should change once we have support for early
1681 // exits in MLIR structured control flow (llvm-project#161575)
1683 llvm::DenseMap<mlir::Block *, mlir::Location> retLocs;
1684 llvm::DenseMap<cir::CaseOp, unsigned> retBlockInCaseIndex;
1685 std::optional<unsigned> normalRetBlockIndex;
1686
1687 // There's usually only one ret block per scope, but this needs to be
1688 // get or create because of potential unreachable return statements, note
1689 // that for those, all source location maps to the first one found.
1690 mlir::Block *createRetBlock(CIRGenFunction &cgf, mlir::Location loc) {
1691 assert((isa_and_nonnull<cir::CaseOp>(
1692 cgf.builder.getBlock()->getParentOp()) ||
1693 retBlocks.size() == 0) &&
1694 "only switches can hold more than one ret block");
1695
1696 // Create the return block but don't hook it up just yet.
1697 mlir::OpBuilder::InsertionGuard guard(cgf.builder);
1698 auto *b = cgf.builder.createBlock(cgf.builder.getBlock()->getParent());
1699 retBlocks.push_back(b);
1700 updateRetLoc(b, loc);
1701 return b;
1702 }
1703
1704 cir::ReturnOp emitReturn(mlir::Location loc);
1705 void emitImplicitReturn();
1706
1707 public:
1709 mlir::Location getRetLoc(mlir::Block *b) { return retLocs.at(b); }
1710 void updateRetLoc(mlir::Block *b, mlir::Location loc) {
1711 retLocs.insert_or_assign(b, loc);
1712 }
1713
1714 mlir::Block *getOrCreateRetBlock(CIRGenFunction &cgf, mlir::Location loc) {
1715 // Check if we're inside a case region
1716 if (auto caseOp = mlir::dyn_cast_if_present<cir::CaseOp>(
1717 cgf.builder.getBlock()->getParentOp())) {
1718 auto iter = retBlockInCaseIndex.find(caseOp);
1719 if (iter != retBlockInCaseIndex.end()) {
1720 // Reuse existing return block
1721 mlir::Block *ret = retBlocks[iter->second];
1722 updateRetLoc(ret, loc);
1723 return ret;
1724 }
1725 // Create new return block
1726 mlir::Block *ret = createRetBlock(cgf, loc);
1727 retBlockInCaseIndex[caseOp] = retBlocks.size() - 1;
1728 return ret;
1729 }
1730
1731 if (normalRetBlockIndex) {
1732 mlir::Block *ret = retBlocks[*normalRetBlockIndex];
1733 updateRetLoc(ret, loc);
1734 return ret;
1735 }
1736
1737 mlir::Block *ret = createRetBlock(cgf, loc);
1738 normalRetBlockIndex = retBlocks.size() - 1;
1739 return ret;
1740 }
1741
1742 mlir::Block *getEntryBlock() { return entryBlock; }
1743 };
1744
1746
1748
1750 QualType type);
1751
1752 void pushDestroy(QualType::DestructionKind dtorKind, Address addr,
1753 QualType type);
1754
1756 Destroyer *destroyer);
1757
1759 QualType type, Destroyer *destroyer,
1760 bool useEHCleanupForArray,
1761 const clang::ValueDecl *extendingDecl);
1762
1764
1765 void pushIrregularPartialArrayCleanup(mlir::Value arrayBegin,
1766 Address arrayEndPointer,
1767 QualType elementType,
1768 CharUnits elementAlign,
1769 Destroyer *destroyer);
1770
1771 /// Start generating a thunk function.
1772 void startThunk(cir::FuncOp fn, GlobalDecl gd,
1773 const CIRGenFunctionInfo &fnInfo, bool isUnprototyped);
1774
1775 /// Finish generating a thunk function.
1776 void finishThunk();
1777
1778 /// Generate code for a thunk function.
1779 void generateThunk(cir::FuncOp fn, SourceRange fnLoc,
1780 const CIRGenFunctionInfo &fnInfo, GlobalDecl gd,
1781 const ThunkInfo &thunk, bool isUnprototyped);
1782
1783 /// ----------------------
1784 /// CIR emit functions
1785 /// ----------------------
1786public:
1787 bool getAArch64SVEProcessedOperands(unsigned builtinID, const CallExpr *expr,
1789 clang::SVETypeFlags typeFlags);
1790 mlir::Value emitSVEPredicateCast(mlir::Value pred, unsigned minNumElts,
1791 mlir::Location loc);
1792 std::optional<mlir::Value>
1793 emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr,
1795 llvm::Triple::ArchType arch);
1796 std::optional<mlir::Value> emitAArch64SMEBuiltinExpr(unsigned builtinID,
1797 const CallExpr *expr);
1798 std::optional<mlir::Value> emitAArch64SVEBuiltinExpr(unsigned builtinID,
1799 const CallExpr *expr);
1800 cir::VectorType getSVEType(const SVETypeFlags &typeFlags);
1801
1802 mlir::Value emitAlignmentAssumption(mlir::Value ptrValue, QualType ty,
1803 SourceLocation loc,
1804 SourceLocation assumptionLoc,
1805 int64_t alignment,
1806 mlir::Value offsetValue = nullptr);
1807
1808 mlir::Value emitAlignmentAssumption(mlir::Value ptrValue, const Expr *expr,
1809 SourceLocation assumptionLoc,
1810 int64_t alignment,
1811 mlir::Value offsetValue = nullptr);
1812
1813 bool emitLifetimeStartOp(mlir::Location loc, mlir::Value addr);
1814 void emitLifetimeEndOp(mlir::Location loc, mlir::Value addr);
1815
1816private:
1817 void emitAndUpdateRetAlloca(clang::QualType type, mlir::Location loc,
1818 clang::CharUnits alignment);
1819
1820 CIRGenCallee emitDirectCallee(const GlobalDecl &gd);
1821
1822public:
1824 llvm::StringRef fieldName,
1825 unsigned fieldIndex);
1826
1827 mlir::Value emitAlloca(llvm::StringRef name, mlir::Type ty,
1828 mlir::Location loc, clang::CharUnits alignment,
1829 bool insertIntoFnEntryBlock,
1830 mlir::Value arraySize = nullptr);
1831 mlir::Value emitAlloca(llvm::StringRef name, mlir::Type ty,
1832 mlir::Location loc, clang::CharUnits alignment,
1833 mlir::OpBuilder::InsertPoint ip,
1834 mlir::Value arraySize = nullptr);
1835
1836 void emitAggregateStore(mlir::Value value, Address dest);
1837
1838 void emitAggExpr(const clang::Expr *e, AggValueSlot slot);
1839
1841
1843
1844 /// Emit an aggregate copy.
1845 ///
1846 /// \param isVolatile \c true iff either the source or the destination is
1847 /// volatile.
1848 /// \param MayOverlap Whether the tail padding of the destination might be
1849 /// occupied by some other object. More efficient code can often be
1850 /// generated if not.
1851 void emitAggregateCopy(LValue dest, LValue src, QualType eltTy,
1852 AggValueSlot::Overlap_t mayOverlap,
1853 bool isVolatile = false);
1854
1855 /// Emit code to compute the specified expression which can have any type. The
1856 /// result is returned as an RValue struct. If this is an aggregate
1857 /// expression, the aggloc/agglocvolatile arguments indicate where the result
1858 /// should be returned.
1861 bool ignoreResult = false);
1862
1863 /// Emits the code necessary to evaluate an arbitrary expression into the
1864 /// given memory location.
1865 void emitAnyExprToMem(const Expr *e, Address location, Qualifiers quals,
1866 bool isInitializer);
1867
1868 /// Similarly to emitAnyExpr(), however, the result will always be accessible
1869 /// even if no aggregate location is provided.
1871
1872 void emitAnyExprToExn(const Expr *e, Address addr);
1873
1874 void emitArrayDestroy(mlir::Value begin, mlir::Value numElements,
1875 QualType elementType, CharUnits elementAlign,
1876 Destroyer *destroyer);
1877
1878 mlir::Value emitArrayLength(const clang::ArrayType *arrayType,
1879 QualType &baseType, Address &addr);
1882
1884
1886
1888 LValueBaseInfo *baseInfo = nullptr);
1889
1890 std::pair<mlir::Value, mlir::Type>
1892 QualType inputType, std::string &constraintString,
1893 SourceLocation loc);
1894 std::pair<mlir::Value, mlir::Type>
1895 emitAsmInput(const TargetInfo::ConstraintInfo &info, const Expr *inputExpr,
1896 std::string &constraintString);
1897 mlir::LogicalResult emitAsmStmt(const clang::AsmStmt &s);
1898
1900 void emitAtomicInit(Expr *init, LValue dest);
1901 void emitAtomicStore(RValue rvalue, LValue dest, bool isInit);
1902 void emitAtomicStore(RValue rvalue, LValue dest, cir::MemOrder order,
1903 bool isVolatile, bool isInit);
1905 const Expr *memOrder, bool isStore, bool isLoad, bool isFence,
1906 llvm::function_ref<void(cir::MemOrder)> emitAtomicOp);
1907
1908 mlir::Value makeBinaryAtomicValue(
1909 cir::AtomicFetchKind kind, const clang::CallExpr *expr,
1910 mlir::Type *originalArgType = nullptr,
1911 mlir::Value *emittedArgValue = nullptr,
1912 cir::MemOrder ordering = cir::MemOrder::SequentiallyConsistent);
1913
1914 /// Emit `cir.atomic.cmpxchg`. Returns the old value, or the success flag
1915 /// when `returnBool` is true.
1916 mlir::Value emitAtomicCmpXchg(
1917 const clang::CallExpr *expr, bool returnBool,
1918 cir::MemOrder successOrder = cir::MemOrder::SequentiallyConsistent,
1919 cir::MemOrder failureOrder = cir::MemOrder::SequentiallyConsistent,
1920 cir::SyncScopeKind scope = cir::SyncScopeKind::System);
1921
1922 mlir::LogicalResult emitAttributedStmt(const AttributedStmt &s);
1923
1924 AutoVarEmission emitAutoVarAlloca(const clang::VarDecl &d,
1925 mlir::OpBuilder::InsertPoint ip = {});
1926
1928 AggValueSlot slot = AggValueSlot::ignored());
1930
1931 /// Emit code and set up symbol table for a variable declaration with auto,
1932 /// register, or no storage class specifier. These turn into simple stack
1933 /// objects, globals depending on target.
1934 void emitAutoVarDecl(const clang::VarDecl &d);
1935
1936 void emitAutoVarCleanups(const AutoVarEmission &emission);
1937
1938 /// Emit a loop's condition-variable declaration. This needs special handling
1939 /// so that we can manage per-iteration cleanups for the loop condition.
1940 /// \p extendedTemporaries are the types of the temporaries with a destructor
1941 /// that its initializer lifetime-extends (see
1942 /// getLifetimeExtendedTemporariesWithDestructor).
1944 CapturedCleanups &condCleanup,
1945 llvm::ArrayRef<QualType> extendedTemporaries);
1946
1947 /// The types of the temporaries with a destructor that the initializer of
1948 /// the variable \p d, which has automatic storage duration, lifetime-extends.
1951
1952 /// Emit the initializer for an allocated variable. If this call is not
1953 /// associated with the call to emitAutoVarAlloca (as the address of the
1954 /// emission is not directly an alloca), the allocatedSeparately parameter can
1955 /// be used to suppress the assertions. However, this should only be used in
1956 /// extreme cases, as it doesn't properly reflect the language/AST.
1957 void emitAutoVarInit(const AutoVarEmission &emission);
1958 void emitAutoVarTypeCleanup(const AutoVarEmission &emission,
1960
1961 void maybeEmitDeferredVarDeclInit(const VarDecl *vd);
1962
1963 void emitBaseInitializer(mlir::Location loc, const CXXRecordDecl *classDecl,
1964 CXXCtorInitializer *baseInit);
1965
1967
1968 mlir::LogicalResult emitBreakStmt(const clang::BreakStmt &s);
1969
1970 RValue emitBuiltinExpr(const clang::GlobalDecl &gd, unsigned builtinID,
1971 const clang::CallExpr *e, ReturnValueSlot returnValue);
1972
1973 /// Returns a Value corresponding to the size of the given expression by
1974 /// emitting a `cir.objsize` operation.
1975 ///
1976 /// \param e The expression whose object size to compute
1977 /// \param type Determines the semantics of the object size computation.
1978 /// The type parameter is a 2-bit value where:
1979 /// bit 0 (type & 1): 0 = whole object, 1 = closest subobject
1980 /// bit 1 (type & 2): 0 = maximum size, 2 = minimum size
1981 /// \param resType The result type for the size value
1982 /// \param emittedE Optional pre-emitted pointer value. If non-null, we'll
1983 /// call `cir.objsize` on this value rather than emitting e.
1984 /// \param isDynamic If true, allows runtime evaluation via dynamic mode
1985 mlir::Value emitBuiltinObjectSize(const clang::Expr *e, unsigned type,
1986 cir::IntType resType, mlir::Value emittedE,
1987 bool isDynamic);
1988
1989 mlir::Value evaluateOrEmitBuiltinObjectSize(const clang::Expr *e,
1990 unsigned type,
1991 cir::IntType resType,
1992 mlir::Value emittedE,
1993 bool isDynamic);
1994
1995 int64_t getAccessedFieldNo(unsigned idx, mlir::ArrayAttr elts);
1996
1997 /// Return the CIR signature of the LLVM intrinsic \p id, resolving its
1998 /// overloaded types to \p overloadTys. Integer types are returned signed.
1999 cir::FuncType getIntrinsicType(llvm::Intrinsic::ID id,
2000 llvm::ArrayRef<mlir::Type> overloadTys = {});
2001
2002 /// Emit a simple LLVM intrinsic that takes N scalar arguments. The intrinsic
2003 /// name is used verbatim; any overload mangling (e.g. `.f32`, `.p1`) must be
2004 /// baked into \p intrinName by the caller. The result type defaults to the
2005 /// type of the first argument; pass \p resultType for intrinsics whose result
2006 /// differs from the operand, such as a vector reduction that returns the
2007 /// element type. Unlike classic CodeGen, CIR has no intrinsic registry to
2008 /// derive the result type from the operand, so it must be supplied here.
2009 template <unsigned N>
2010 [[maybe_unused]] RValue
2012 llvm::StringRef intrinName,
2013 mlir::Type resultType = {}) {
2014 static_assert(N, "expect non-empty argument");
2015 mlir::Type cirTy =
2016 resultType ? resultType : convertType(e->getArg(0)->getType());
2018 for (unsigned i = 0; i < N; ++i)
2019 args.push_back(emitScalarExpr(e->getArg(i)));
2020 const auto call = cir::LLVMIntrinsicCallOp::create(
2021 builder, getLoc(e->getExprLoc()), builder.getStringAttr(intrinName),
2022 cirTy, args);
2023 return RValue::get(call->getResult(0));
2024 }
2025
2026 RValue emitCall(const CIRGenFunctionInfo &funcInfo,
2027 const CIRGenCallee &callee, ReturnValueSlot returnValue,
2028 const CallArgList &args, cir::CIRCallOpInterface *callOp,
2029 bool isMustTail, SourceRange clangLoc);
2032 const CallArgList &args, bool isMustTail,
2033 cir::CIRCallOpInterface *callOrTryCall = nullptr) {
2034 assert(currSrcLoc && "source location must have been set");
2035 return emitCall(funcInfo, callee, returnValue, args, callOrTryCall,
2036 isMustTail, *currSrcLoc);
2037 }
2038
2039 RValue emitCall(clang::QualType calleeTy, const CIRGenCallee &callee,
2041
2042 /// Emit the call and return for a thunk function.
2043 void emitCallAndReturnForThunk(cir::FuncOp callee, SourceRange fnLoc,
2044 const ThunkInfo *thunk, bool isUnprototyped);
2045
2046 void emitCallArg(CallArgList &args, const clang::Expr *e,
2047 clang::QualType argType);
2048 void emitCallArgs(
2049 CallArgList &args, PrototypeWrapper prototype,
2050 llvm::iterator_range<clang::CallExpr::const_arg_iterator> argRange,
2051 AbstractCallee callee = AbstractCallee(), unsigned paramsToSkip = 0);
2055
2059
2060 template <typename T>
2061 mlir::LogicalResult emitCaseDefaultCascade(const T *stmt, mlir::Type condType,
2062 mlir::ArrayAttr value,
2063 cir::CaseOpKind kind,
2064 bool buildingTopLevelCase);
2065
2067
2068 mlir::LogicalResult emitCaseStmt(const clang::CaseStmt &s,
2069 mlir::Type condType,
2070 bool buildingTopLevelCase);
2071
2072 LValue emitCastLValue(const CastExpr *e);
2073
2074 /// Emits an argument for a call to a `__builtin_assume`. If the builtin
2075 /// sanitizer is enabled, a runtime check is also emitted.
2076 mlir::Value emitCheckedArgForAssume(const Expr *e);
2077
2078 /// Emit a conversion from the specified complex type to the specified
2079 /// destination type, where the destination type is an LLVM scalar type.
2080 mlir::Value emitComplexToScalarConversion(mlir::Value src, QualType srcTy,
2081 QualType dstTy, SourceLocation loc);
2082
2085
2087
2088 mlir::LogicalResult emitCoroutineBody(const CoroutineBodyStmt &s);
2089 cir::CoroEndOp emitCoroEndBuiltinCall(const CallExpr *e);
2090 cir::CoroIdOp emitCoroIDBuiltinCall(const CallExpr *e);
2091 cir::CoroAllocOp emitCoroAllocBuiltinCall(const CallExpr *e);
2092 cir::CoroBeginOp emitCoroBeginBuiltinCall(const CallExpr *e);
2093 cir::CoroPromiseOp emitCoroPromiseBuiltinCall(const CallExpr *e);
2094 cir::CoroDoneOp emitCoroDoneBuiltinCall(const CallExpr *e);
2095 cir::CoroResumeOp emitCoroResumeBuiltinCall(const CallExpr *e);
2096 cir::CoroDestroyOp emitCoroDestroyBuiltinCall(const CallExpr *e);
2097 cir::CoroNoopOp emitCoroNoopBuiltinCall(const CallExpr *e);
2098 cir::CoroSuspendOp emitCoroSuspendBuiltinCall(const CallExpr *e);
2099
2100 cir::CoroSizeOp emitCoroSizeBuiltinCall(const CallExpr *e);
2101 cir::CoroAlignOp emitCoroAlignBuiltinCall(const CallExpr *e);
2102 cir::CoroFreeOp emitCoroFreeBuiltin(const CallExpr *e);
2104
2105 void emitDestroy(Address addr, QualType type, Destroyer *destroyer);
2106
2108
2109 mlir::LogicalResult emitContinueStmt(const clang::ContinueStmt &s);
2110
2111 mlir::LogicalResult emitCoreturnStmt(const CoreturnStmt &s);
2112
2114 AggValueSlot dest);
2115
2118 Address arrayBegin, const CXXConstructExpr *e,
2119 bool newPointerIsChecked,
2120 bool zeroInitialize = false);
2122 mlir::Value numElements, Address arrayBase,
2123 const CXXConstructExpr *e,
2124 bool newPointerIsChecked, bool zeroInitialize,
2125 Address endOfInit);
2127 clang::CXXCtorType type, bool forVirtualBase,
2128 bool delegating, AggValueSlot thisAVS,
2129 const clang::CXXConstructExpr *e);
2130
2132 clang::CXXCtorType type, bool forVirtualBase,
2133 bool delegating, Address thisAddr,
2135
2137 bool forVirtualBase, Address thisAddr,
2138 bool inheritedFromVBase,
2139 const CXXInheritedCtorInitExpr *e);
2140
2142 SourceLocation loc, const CXXConstructorDecl *d, CXXCtorType ctorType,
2143 bool forVirtualBase, bool delegating, CallArgList &args);
2144
2145 void emitCXXDeleteExpr(const CXXDeleteExpr *e);
2146
2148 bool forVirtualBase, bool delegating,
2149 Address thisAddr, QualType thisTy);
2150
2152 mlir::Value thisVal, QualType thisTy,
2153 mlir::Value implicitParam,
2154 QualType implicitParamTy, const CallExpr *e);
2155
2156 mlir::LogicalResult emitCXXForRangeStmt(const CXXForRangeStmt &s,
2158
2161
2163 const Expr *e, Address base, mlir::Value memberPtr,
2164 const MemberPointerType *memberPtrType, LValueBaseInfo *baseInfo);
2165
2167 const clang::CXXMethodDecl *md, const CIRGenCallee &callee,
2168 ReturnValueSlot returnValue, mlir::Value thisPtr,
2169 mlir::Value implicitParam, clang::QualType implicitParamTy,
2170 const clang::CallExpr *ce, CallArgList *rtlArgs);
2171
2173 const clang::CallExpr *ce, const clang::CXXMethodDecl *md,
2174 ReturnValueSlot returnValue, bool hasQualifier,
2175 clang::NestedNameSpecifier qualifier, bool isArrow,
2176 const clang::Expr *base);
2177
2180
2181 mlir::Value emitCXXNewExpr(const CXXNewExpr *e);
2182
2183 void emitNewArrayInitializer(const CXXNewExpr *e, QualType elementType,
2184 mlir::Type elementTy, Address beginPtr,
2185 mlir::Value numElements,
2186 mlir::Value allocSizeWithoutCookie);
2187
2188 /// Create a check for a function parameter that may potentially be
2189 /// declared as non-null.
2190 void emitNonNullArgCheck(RValue rv, QualType argType, SourceLocation argLoc,
2191 AbstractCallee ac, unsigned paramNum);
2192
2194 const CXXMethodDecl *md,
2196
2199
2201
2203 const CallExpr *callExpr,
2205
2206 void emitCXXTemporary(const CXXTemporary *temporary, QualType tempType,
2207 Address ptr);
2208
2209 void emitCXXThrowExpr(const CXXThrowExpr *e);
2210
2212 virtual mlir::LogicalResult operator()(CIRGenFunction &cgf) = 0;
2213 virtual ~cxxTryBodyEmitter() = default;
2214 };
2215
2216 void emitBeginCatch(const CXXCatchStmt *catchStmt, mlir::Value ehToken);
2217
2218 mlir::LogicalResult emitCXXTryStmt(const clang::CXXTryStmt &s,
2219 cxxTryBodyEmitter &bodyCallback,
2220 bool isFnTryBlock = false);
2221 mlir::LogicalResult emitCXXTryStmt(const clang::CXXTryStmt &s);
2222
2224 clang::CXXCtorType ctorType, FunctionArgList &args);
2225
2226 // It's important not to confuse this and emitDelegateCXXConstructorCall.
2227 // Delegating constructors are the C++11 feature. The constructor delegate
2228 // optimization is used to reduce duplication in the base and complete
2229 // constructors where they are substantially the same.
2231 const FunctionArgList &args);
2232
2233 void emitDeleteCall(const FunctionDecl *deleteFD, mlir::Value ptr,
2234 QualType deleteTy);
2235
2236 mlir::LogicalResult emitDoStmt(const clang::DoStmt &s);
2237
2238 mlir::Value emitCXXTypeidExpr(const CXXTypeidExpr *e);
2239 mlir::Value emitDynamicCast(Address thisAddr, const CXXDynamicCastExpr *dce);
2240
2241 /// Emit an expression as an initializer for an object (variable, field, etc.)
2242 /// at the given location. The expression is not necessarily the normal
2243 /// initializer for the object, and the address is not necessarily
2244 /// its normal location.
2245 ///
2246 /// \param init the initializing expression
2247 /// \param d the object to act as if we're initializing
2248 /// \param lvalue the lvalue to initialize
2249 /// \param capturedByInit true if \p d is a __block variable whose address is
2250 /// potentially changed by the initializer
2251 void emitExprAsInit(const clang::Expr *init, const clang::ValueDecl *d,
2252 LValue lvalue, bool capturedByInit = false);
2253
2254 mlir::LogicalResult emitFunctionBody(const clang::Stmt *body);
2255
2256 mlir::LogicalResult emitGotoStmt(const clang::GotoStmt &s);
2257
2258 mlir::LogicalResult emitIndirectGotoStmt(const IndirectGotoStmt &s);
2259
2261
2263 clang::Expr *init);
2264
2266
2267 mlir::Value emitPromotedComplexExpr(const Expr *e, QualType promotionType);
2268
2269 mlir::Value emitPromotedScalarExpr(const Expr *e, QualType promotionType);
2270
2271 mlir::Value emitPromotedValue(mlir::Value result, QualType promotionType);
2272
2273 void emitReturnOfRValue(mlir::Location loc, RValue rv, QualType ty);
2274
2275 mlir::Value emitRuntimeCall(mlir::Location loc, cir::FuncOp callee,
2277 mlir::NamedAttrList attrs = {});
2278
2279 void emitInvariantStart(CharUnits size, mlir::Value addr, mlir::Location loc);
2280
2281 /// Emit the computation of the specified expression of scalar type.
2282 mlir::Value emitScalarExpr(const clang::Expr *e,
2283 bool ignoreResultAssign = false);
2284
2285 mlir::Value emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv);
2286
2287 /// Build a debug stoppoint if we are emitting debug info.
2288 void emitStopPoint(const Stmt *s);
2289
2290 // Build CIR for a statement. useCurrentScope should be true if no
2291 // new scopes need be created when finding a compound statement.
2292 mlir::LogicalResult emitStmt(const clang::Stmt *s, bool useCurrentScope,
2293 llvm::ArrayRef<const Attr *> attrs = {});
2294
2295 mlir::LogicalResult emitSimpleStmt(const clang::Stmt *s,
2296 bool useCurrentScope);
2297
2298 mlir::LogicalResult emitForStmt(const clang::ForStmt &s);
2299
2300 void emitForwardingCallToLambda(const CXXMethodDecl *lambdaCallOperator,
2301 CallArgList &callArgs);
2302
2303 RValue emitCoawaitExpr(const CoawaitExpr &e,
2304 AggValueSlot aggSlot = AggValueSlot::ignored(),
2305 bool ignoreResult = false);
2306
2307 RValue emitCoyieldExpr(const CoyieldExpr &e,
2308 AggValueSlot aggSlot = AggValueSlot::ignored(),
2309 bool ignoreResult = false);
2310 /// Emit the computation of the specified expression of complex type,
2311 /// returning the result.
2312 mlir::Value emitComplexExpr(const Expr *e);
2313
2314 void emitComplexExprIntoLValue(const Expr *e, LValue dest, bool isInit);
2315
2316 mlir::Value emitComplexPrePostIncDec(const UnaryOperator *e, LValue lv);
2317
2318 LValue emitComplexAssignmentLValue(const BinaryOperator *e);
2319 LValue emitComplexCompoundAssignmentLValue(const CompoundAssignOperator *e);
2320 LValue emitScalarCompoundAssignWithComplex(const CompoundAssignOperator *e,
2321 mlir::Value &result);
2322
2323 mlir::LogicalResult
2324 emitCompoundStmt(const clang::CompoundStmt &s, Address *lastValue = nullptr,
2325 AggValueSlot slot = AggValueSlot::ignored());
2326
2327 mlir::LogicalResult
2329 Address *lastValue = nullptr,
2330 AggValueSlot slot = AggValueSlot::ignored());
2331
2332 void emitDecl(const clang::Decl &d, bool evaluateConditionDecl = false);
2333 mlir::LogicalResult emitDeclStmt(const clang::DeclStmt &s);
2334 LValue emitDeclRefLValue(const clang::DeclRefExpr *e);
2335
2336 mlir::LogicalResult emitDefaultStmt(const clang::DefaultStmt &s,
2337 mlir::Type condType,
2338 bool buildingTopLevelCase);
2339
2341 clang::CXXCtorType ctorType,
2342 const FunctionArgList &args,
2344
2345 /// We are performing a delegate call; that is, the current function is
2346 /// delegating to another one. Produce a r-value suitable for passing the
2347 /// given parameter.
2348 void emitDelegateCallArg(CallArgList &args, const clang::VarDecl *param,
2350
2351 /// Emit an `if` on a boolean condition to the specified blocks.
2352 /// FIXME: Based on the condition, this might try to simplify the codegen of
2353 /// the conditional based on the branch.
2354 /// In the future, we may apply code generation simplifications here,
2355 /// similar to those used in classic LLVM codegen
2356 /// See `EmitBranchOnBoolExpr` for inspiration.
2357 mlir::LogicalResult emitIfOnBoolExpr(const clang::Expr *cond,
2358 const clang::Stmt *thenS,
2359 const clang::Stmt *elseS);
2360 cir::IfOp emitIfOnBoolExpr(const clang::Expr *cond,
2361 BuilderCallbackRef thenBuilder,
2362 mlir::Location thenLoc,
2363 BuilderCallbackRef elseBuilder,
2364 std::optional<mlir::Location> elseLoc = {});
2365
2366 /// Build the cir.if for an already-emitted condition value.
2367 cir::IfOp emitIfOnBoolValue(mlir::Value condV, mlir::Location loc,
2368 BuilderCallbackRef thenBuilder,
2369 mlir::Location thenLoc,
2370 BuilderCallbackRef elseBuilder,
2371 std::optional<mlir::Location> elseLoc = {});
2372
2373 mlir::Value emitOpOnBoolExpr(mlir::Location loc, const clang::Expr *cond);
2374
2375 LValue emitPointerToDataMemberBinaryExpr(const BinaryOperator *e);
2376
2377 mlir::LogicalResult emitLabel(const clang::LabelDecl &d);
2378 mlir::LogicalResult emitLabelStmt(const clang::LabelStmt &s);
2379
2380 void emitLambdaDelegatingInvokeBody(const CXXMethodDecl *md);
2381 void emitLambdaStaticInvokeBody(const CXXMethodDecl *md);
2382
2383 mlir::LogicalResult emitIfStmt(const clang::IfStmt &s);
2384
2385 /// Emit code to compute the specified expression,
2386 /// ignoring the result.
2387 void emitIgnoredExpr(const clang::Expr *e);
2388
2389 RValue emitLoadOfBitfieldLValue(LValue lv, SourceLocation loc);
2390
2391 /// Load a complex number from the specified l-value.
2392 mlir::Value emitLoadOfComplex(LValue src, SourceLocation loc);
2393
2394 RValue emitLoadOfExtVectorElementLValue(LValue lv);
2395
2396 /// Given an expression that represents a value lvalue, this method emits
2397 /// the address of the lvalue, then loads the result as an rvalue,
2398 /// returning the rvalue.
2399 RValue emitLoadOfLValue(LValue lv, SourceLocation loc);
2400
2401 Address emitLoadOfReference(LValue refLVal, mlir::Location loc,
2402 LValueBaseInfo *pointeeBaseInfo);
2403 LValue emitLoadOfReferenceLValue(Address refAddr, mlir::Location loc,
2404 QualType refTy, AlignmentSource source);
2405
2406 /// EmitLoadOfScalar - Load a scalar value from an address, taking
2407 /// care to appropriately convert from the memory representation to
2408 /// the LLVM value representation. The l-value must be a simple
2409 /// l-value.
2410 mlir::Value emitLoadOfScalar(LValue lvalue, SourceLocation loc);
2411 mlir::Value emitLoadOfScalar(Address addr, bool isVolatile, QualType ty,
2412 SourceLocation loc, LValueBaseInfo baseInfo,
2413 bool isNontemporal = false);
2414
2415 /// Emit code to compute a designator that specifies the location
2416 /// of the expression.
2417 /// FIXME: document this function better.
2418 LValue emitLValue(const clang::Expr *e);
2419 LValue emitLValueForBitField(LValue base, const FieldDecl *field);
2420 LValue emitLValueForField(LValue base, const clang::FieldDecl *field);
2421
2422 LValue emitLValueForLambdaField(const FieldDecl *field);
2423 LValue emitLValueForLambdaField(const FieldDecl *field,
2424 mlir::Value thisValue);
2425
2426 /// Like emitLValueForField, excpet that if the Field is a reference, this
2427 /// will return the address of the reference and not the address of the value
2428 /// stored in the reference.
2429 LValue emitLValueForFieldInitialization(LValue base,
2430 const clang::FieldDecl *field,
2431 llvm::StringRef fieldName);
2432
2433 LValue emitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *e);
2434
2435 LValue emitMemberExpr(const MemberExpr *e);
2436
2437 /// Emit a musttail call for a thunk with a potentially different ABI.
2438 void emitMustTailThunk(GlobalDecl gd, mlir::Value adjustedThisPtr,
2439 cir::FuncOp callee);
2440
2441 /// Emit a call to an AMDGPU builtin function.
2442 std::optional<mlir::Value> emitAMDGPUBuiltinExpr(unsigned builtinID,
2443 const CallExpr *expr);
2444
2445 /// Emit a call to an NVPTX builtin function.
2446 std::optional<mlir::Value> emitNVPTXBuiltinExpr(unsigned builtinID,
2447 const CallExpr *expr);
2448
2449 /// Emit a device-side printf call for GPU targets.
2450 mlir::Value emitDevicePrintfCallExpr(const CallExpr *expr);
2451
2452 LValue emitOpaqueValueLValue(const OpaqueValueExpr *e);
2453
2454 LValue emitConditionalOperatorLValue(const AbstractConditionalOperator *expr);
2455
2456 /// Given an expression with a pointer type, emit the value and compute our
2457 /// best estimate of the alignment of the pointee.
2458 ///
2459 /// One reasonable way to use this information is when there's a language
2460 /// guarantee that the pointer must be aligned to some stricter value, and
2461 /// we're simply trying to ensure that sufficiently obvious uses of under-
2462 /// aligned objects don't get miscompiled; for example, a placement new
2463 /// into the address of a local variable. In such a case, it's quite
2464 /// reasonable to just ignore the returned alignment when it isn't from an
2465 /// explicit source.
2466 Address emitPointerWithAlignment(const clang::Expr *expr,
2467 LValueBaseInfo *baseInfo = nullptr);
2468
2469 /// Emits a reference binding to the passed in expression.
2470 RValue emitReferenceBindingToExpr(const Expr *e);
2471
2472 mlir::LogicalResult emitReturnStmt(const clang::ReturnStmt &s);
2473
2474 RValue emitRotate(const CallExpr *e, bool isRotateLeft);
2475
2476 mlir::Value emitScalarConstant(const ConstantEmission &constant, Expr *e);
2477
2478 /// Emit a conversion from the specified type to the specified destination
2479 /// type, both of which are CIR scalar types.
2480 mlir::Value emitScalarConversion(mlir::Value src, clang::QualType srcType,
2481 clang::QualType dstType,
2482 clang::SourceLocation loc);
2483
2484 void emitScalarInit(const clang::Expr *init, LValue lvalue,
2485 bool capturedByInit = false);
2486
2487 mlir::Value emitScalarOrConstFoldImmArg(unsigned iceArguments, unsigned idx,
2488 const Expr *argExpr);
2489
2490 void emitStaticVarDecl(const VarDecl &d, cir::GlobalLinkageKind linkage);
2491
2492 /// Emit a guarded initializer for a static local variable.
2493 void emitCXXGuardedInit(const VarDecl &varDecl, cir::GlobalOp globalOp,
2494 bool performInit);
2495
2496 void emitStoreOfComplex(mlir::Location loc, mlir::Value v, LValue dest,
2497 bool isInit);
2498
2499 void emitStoreOfScalar(mlir::Value value, Address addr, bool isVolatile,
2500 clang::QualType ty, LValueBaseInfo baseInfo,
2501 bool isInit = false, bool isNontemporal = false);
2502 void emitStoreOfScalar(mlir::Value value, LValue lvalue, bool isInit);
2503
2504 void emitStoreThroughExtVectorComponentLValue(RValue src, LValue dst);
2505
2506 /// Store the specified rvalue into the specified
2507 /// lvalue, where both are guaranteed to the have the same type, and that
2508 /// type is 'Ty'.
2509 void emitStoreThroughLValue(RValue src, LValue dst, bool isInit = false);
2510
2511 mlir::Value emitStoreThroughBitfieldLValue(RValue src, LValue dstresult);
2512
2513 LValue emitStringLiteralLValue(const StringLiteral *e,
2514 llvm::StringRef name = ".str");
2515
2516 mlir::LogicalResult emitSwitchBody(const clang::Stmt *s);
2517 mlir::LogicalResult emitSwitchCase(const clang::SwitchCase &s,
2518 bool buildingTopLevelCase);
2519 mlir::LogicalResult emitSwitchStmt(const clang::SwitchStmt &s);
2520
2521 mlir::LogicalResult emitSYCLKernelCallStmt(const SYCLKernelCallStmt &s);
2522
2523 void emitSYCLKernelCaller(const clang::OutlinedFunctionDecl *outlinedFnDecl,
2524 cir::FuncOp funcOp, cir::FuncType funcType,
2525 FunctionArgList &args);
2526
2527 /// Remove leftover empty and unreachable blocks from an emitted function.
2528 static void eraseEmptyAndUnusedBlocks(cir::FuncOp func);
2529
2530 std::optional<mlir::Value>
2531 emitTargetBuiltinExpr(unsigned builtinID, const clang::CallExpr *e,
2532 ReturnValueSlot &returnValue);
2533
2534 /// Emit a diagnostic if the target features required by \p targetDecl are
2535 /// not available in the calling function. Mirrors CodeGenFunction behavior.
2536 void checkTargetFeatures(const clang::CallExpr *e,
2537 const clang::FunctionDecl *targetDecl);
2538 void checkTargetFeatures(clang::SourceLocation loc,
2539 const clang::FunctionDecl *targetDecl);
2540
2541 /// Given a value and its clang type, returns the value casted to its memory
2542 /// representation.
2543 /// Note: CIR defers most of the special casting to the final lowering passes
2544 /// to conserve the high level information.
2545 mlir::Value emitToMemory(mlir::Value value, clang::QualType ty);
2546
2547 /// EmitFromMemory - Change a scalar value from its memory
2548 /// representation to its value representation.
2549 mlir::Value emitFromMemory(mlir::Value value, clang::QualType ty);
2550
2551 /// Emit a trap instruction, which is used to abort the program in an abnormal
2552 /// way, usually for debugging purposes.
2553 /// \p createNewBlock indicates whether to create a new block for the IR
2554 /// builder. Since the `cir.trap` operation is a terminator, operations that
2555 /// follow a trap cannot be emitted after `cir.trap` in the same block. To
2556 /// ensure these operations get emitted successfully, you need to create a new
2557 /// dummy block and set the insertion point there before continuing from the
2558 /// trap operation.
2559 void emitTrap(mlir::Location loc, bool createNewBlock);
2560
2561 LValue emitUnaryOpLValue(const clang::UnaryOperator *e);
2562
2563 mlir::Value emitUnPromotedValue(mlir::Value result, QualType unPromotionType);
2564
2565 /// Emit a reached-unreachable diagnostic if \p loc is valid and runtime
2566 /// checking is enabled. Otherwise, just emit an unreachable instruction.
2567 /// \p createNewBlock indicates whether to create a new block for the IR
2568 /// builder. Since the `cir.unreachable` operation is a terminator, operations
2569 /// that follow an unreachable point cannot be emitted after `cir.unreachable`
2570 /// in the same block. To ensure these operations get emitted successfully,
2571 /// you need to create a dummy block and set the insertion point there before
2572 /// continuing from the unreachable point.
2573 void emitUnreachable(clang::SourceLocation loc, bool createNewBlock);
2574
2575 /// This method handles emission of any variable declaration
2576 /// inside a function, including static vars etc.
2577 void emitVarDecl(const clang::VarDecl &d);
2578
2579 void emitVariablyModifiedType(QualType ty);
2580
2581 mlir::LogicalResult emitWhileStmt(const clang::WhileStmt &s);
2582
2583 std::optional<mlir::Value> emitRISCVBuiltinExpr(unsigned builtinID,
2584 const CallExpr *expr);
2585 cir::GetGlobalOp createGetCpuModel(mlir::Location loc);
2586 cir::GetGlobalOp createGetCpuFeatures2(mlir::Location loc);
2587 mlir::Value emitX86CpuIs(const CallExpr *expr);
2588 mlir::Value emitX86CpuIs(mlir::Location loc, StringRef cpuStr);
2589 mlir::Value emitX86CpuSupports(const CallExpr *expr);
2590 mlir::Value emitX86CpuSupports(mlir::Location loc,
2591 ArrayRef<StringRef> FeatureStrs);
2592 mlir::Value emitX86CpuSupports(mlir::Location loc,
2593 std::array<uint32_t, 4> FeatureMask);
2594 mlir::Value emitX86CpuInit(mlir::Location loc);
2595 std::optional<mlir::Value> emitX86BuiltinExpr(unsigned builtinID,
2596 const CallExpr *expr);
2597
2598 /// Given an assignment `*lhs = rhs`, emit a test that checks if \p rhs is
2599 /// nonnull, if 1\p LHS is marked _Nonnull.
2600 void emitNullabilityCheck(LValue lhs, mlir::Value rhs,
2601 clang::SourceLocation loc);
2602
2603 /// An object to manage conditionally-evaluated expressions.
2605 CIRGenFunction &cgf;
2606
2607 /// The insertion point that precedes the conditional, stored as the
2608 /// enclosing block and the operation immediately before that point. Later
2609 /// operations (the condition, cleanup scopes) can be appended without
2610 /// moving this point. A null \c anchorAfter means the insertion point is
2611 /// the start of \c anchorBlock.
2612 mlir::Block *anchorBlock;
2613 mlir::Operation *anchorAfter = nullptr;
2614
2615 public:
2616 /// \p loc is the location of the conditional expression. It is used for
2617 /// the cleanup scope this may open.
2618 ConditionalEvaluation(CIRGenFunction &cgf, mlir::Location loc) : cgf(cgf) {
2619 // Open the cleanup scope that hosts cleanups deferred from inside this
2620 // conditional (see deferredConditionalCleanupStack). Only the outermost
2621 // conditional opens one, and only while a FullExprCleanupScope is
2622 // active to close it. When nothing is deferred into it the cleanup
2623 // region stays trivial and canonicalization inlines the scope away.
2624 if (cgf.currentFullExprCleanupScope && !cgf.isInConditionalBranch()) {
2625 cir::CleanupKind cleanupKind = cgf.getLangOpts().Exceptions
2626 ? cir::CleanupKind::All
2627 : cir::CleanupKind::Normal;
2628 cir::CleanupScopeOp scope = cir::CleanupScopeOp::create(
2629 cgf.builder, loc, cleanupKind,
2630 /*bodyBuilder=*/[](mlir::OpBuilder &, mlir::Location) {},
2631 /*cleanupBuilder=*/[](mlir::OpBuilder &, mlir::Location) {});
2632 cgf.conditionalCleanupScopes.push_back(
2633 {scope, cgf.deferredConditionalCleanupStack.size()});
2634 cgf.builder.setInsertionPointToEnd(&scope.getBodyRegion().front());
2635 }
2636
2637 anchorBlock = cgf.builder.getInsertionBlock();
2638 assert(anchorBlock && "conditional evaluation needs an insertion point");
2639 mlir::Block::iterator ip = cgf.builder.getInsertionPoint();
2640 if (ip != anchorBlock->begin())
2641 anchorAfter = &*std::prev(ip);
2642 }
2643
2645 assert(cgf.outermostConditional != this);
2646 if (!cgf.outermostConditional)
2647 cgf.outermostConditional = this;
2648 }
2649
2651 assert(cgf.outermostConditional != nullptr);
2652 if (cgf.outermostConditional == this)
2653 cgf.outermostConditional = nullptr;
2654 }
2655
2656 /// Records \p op as the last operation emitted at the pre-conditional
2657 /// insertion point, so that a later emission lands after it rather than
2658 /// ahead of it.
2659 void advanceInsertPoint(mlir::Operation *op) { anchorAfter = op; }
2660
2661 /// Returns the insertion point which will be executed prior to each
2662 /// evaluation of the conditional code. In LLVM OG, this method
2663 /// is called getStartingBlock.
2664 mlir::OpBuilder::InsertPoint getInsertPoint() const {
2665 if (!anchorAfter)
2666 return mlir::OpBuilder::InsertPoint(anchorBlock, anchorBlock->begin());
2667 return mlir::OpBuilder::InsertPoint(
2668 anchorAfter->getBlock(), std::next(anchorAfter->getIterator()));
2669 }
2670 };
2671
2673 std::optional<LValue> lhs{}, rhs{};
2674 mlir::Value result{};
2675 };
2676
2677 // Return true if we're currently emitting one branch or the other of a
2678 // conditional expression.
2679 bool isInConditionalBranch() const { return outermostConditional != nullptr; }
2680
2681 void setBeforeOutermostConditional(mlir::Value value, Address addr) {
2682 assert(isInConditionalBranch());
2683 {
2684 mlir::OpBuilder::InsertionGuard guard(builder);
2685 builder.restoreInsertionPoint(outermostConditional->getInsertPoint());
2686 cir::StoreOp store = builder.createStore(
2687 value.getLoc(), value, addr, /*isVolatile=*/false,
2688 /*isNontemporal=*/false,
2689 mlir::IntegerAttr::get(
2690 mlir::IntegerType::get(value.getContext(), 64),
2691 (uint64_t)addr.getAlignment().getAsAlign().value()));
2692 outermostConditional->advanceInsertPoint(store);
2693 }
2694 }
2695
2696 // Points to the outermost active conditional control. This is used so that
2697 // we know if a temporary should be destroyed conditionally.
2699
2700 /// An RAII object to record that we're evaluating a statement
2701 /// expression.
2703 CIRGenFunction &cgf;
2704
2705 /// We have to save the outermost conditional: cleanups in a
2706 /// statement expression aren't conditional just because the
2707 /// StmtExpr is.
2708 ConditionalEvaluation *savedOutermostConditional;
2709
2710 public:
2712 : cgf(cgf), savedOutermostConditional(cgf.outermostConditional) {
2713 cgf.outermostConditional = nullptr;
2714 }
2715
2717 cgf.outermostConditional = savedOutermostConditional;
2718 }
2719 };
2720
2721 template <typename FuncTy>
2722 ConditionalInfo emitConditionalBlocks(const AbstractConditionalOperator *e,
2723 const FuncTy &branchGenFunc);
2724
2725 mlir::Value emitTernaryOnBoolExpr(const clang::Expr *cond, mlir::Location loc,
2726 const clang::Stmt *thenS,
2727 const clang::Stmt *elseS);
2728
2729 /// Build a "reference" to a va_list; this is either the address or the value
2730 /// of the expression, depending on how va_list is defined.
2731 Address emitVAListRef(const Expr *e);
2732
2733 /// Emits the start of a CIR variable-argument operation (`cir.va_start`)
2734 ///
2735 /// \param vaList A reference to the \c va_list as emitted by either
2736 /// \c emitVAListRef or \c emitMSVAListRef.
2737 void emitVAStart(mlir::Value vaList);
2738
2739 /// Emits the end of a CIR variable-argument operation (`cir.va_start`)
2740 ///
2741 /// \param vaList A reference to the \c va_list as emitted by either
2742 /// \c emitVAListRef or \c emitMSVAListRef.
2743 void emitVAEnd(mlir::Value vaList);
2744
2745 /// Generate code to get an argument from the passed in pointer
2746 /// and update it accordingly.
2747 ///
2748 /// \param ve The \c VAArgExpr for which to generate code.
2749 ///
2750 /// \param vaListAddr Receives a reference to the \c va_list as emitted by
2751 /// either \c emitVAListRef or \c emitMSVAListRef.
2752 ///
2753 /// \returns SSA value with the argument.
2754 mlir::Value emitVAArg(VAArgExpr *ve);
2755
2756 /// ----------------------
2757 /// CIR build helpers
2758 /// -----------------
2759public:
2760 cir::AllocaOp createTempAlloca(mlir::Type ty, mlir::Location loc,
2761 const Twine &name = "tmp",
2762 mlir::Value arraySize = nullptr,
2763 bool insertIntoFnEntryBlock = false);
2764 cir::AllocaOp createTempAlloca(mlir::Type ty, mlir::Location loc,
2765 const Twine &name = "tmp",
2766 mlir::OpBuilder::InsertPoint ip = {},
2767 mlir::Value arraySize = nullptr);
2768 Address createTempAlloca(mlir::Type ty, CharUnits align, mlir::Location loc,
2769 const Twine &name = "tmp",
2770 mlir::Value arraySize = nullptr,
2771 Address *alloca = nullptr,
2772 mlir::OpBuilder::InsertPoint ip = {});
2773 Address createTempAlloca(mlir::Type ty,
2774 mlir::ptr::MemorySpaceAttrInterface destAddrSpace,
2775 CharUnits align, mlir::Location loc,
2776 const Twine &name = "tmp",
2777 mlir::Value arraySize = nullptr,
2778 Address *alloca = nullptr,
2779 mlir::OpBuilder::InsertPoint ip = {});
2780 Address createTempAllocaWithoutCast(mlir::Type ty, CharUnits align,
2781 mlir::Location loc,
2782 const Twine &name = "tmp",
2783 mlir::Value arraySize = nullptr,
2784 mlir::OpBuilder::InsertPoint ip = {});
2785 Address
2786 maybeCastStackAddressSpace(Address alloca,
2787 mlir::ptr::MemorySpaceAttrInterface destAddrSpace,
2788 mlir::Value arraySize = nullptr);
2789 Address createDefaultAlignTempAlloca(mlir::Type ty, mlir::Location loc,
2790 const Twine &name);
2791
2792 /// Create a temporary memory object of the given type, with
2793 /// appropriate alignmen and cast it to the default address space. Returns
2794 /// the original alloca instruction by \p Alloca if it is not nullptr.
2795 Address createMemTemp(QualType t, mlir::Location loc,
2796 const Twine &name = "tmp", Address *alloca = nullptr,
2797 mlir::OpBuilder::InsertPoint ip = {});
2798 Address createMemTemp(QualType t, CharUnits align, mlir::Location loc,
2799 const Twine &name = "tmp", Address *alloca = nullptr,
2800 mlir::OpBuilder::InsertPoint ip = {});
2801 Address createMemTempWithoutCast(QualType t, mlir::Location loc,
2802 const Twine &name = "tmp");
2803
2804 mlir::Value performAddrSpaceCast(mlir::Value v, mlir::Type destTy) const {
2805 if (cir::GlobalOp globalOp = v.getDefiningOp<cir::GlobalOp>())
2806 cgm.errorNYI("Global op addrspace cast");
2807 return builder.createAddrSpaceCast(v, destTy);
2808 }
2809
2810 //===--------------------------------------------------------------------===//
2811 // OpenMP Emission
2812 //===--------------------------------------------------------------------===//
2813public:
2814 mlir::LogicalResult emitOMPScopeDirective(const OMPScopeDirective &s);
2815 mlir::LogicalResult emitOMPErrorDirective(const OMPErrorDirective &s);
2816 mlir::LogicalResult emitOMPParallelDirective(const OMPParallelDirective &s);
2817 mlir::LogicalResult emitOMPTaskwaitDirective(const OMPTaskwaitDirective &s);
2818 mlir::LogicalResult emitOMPTaskyieldDirective(const OMPTaskyieldDirective &s);
2819 mlir::LogicalResult emitOMPBarrierDirective(const OMPBarrierDirective &s);
2820 mlir::LogicalResult emitOMPMetaDirective(const OMPMetaDirective &s);
2821 mlir::LogicalResult emitOMPCanonicalLoop(const OMPCanonicalLoop &s);
2822 mlir::LogicalResult emitOMPSimdDirective(const OMPSimdDirective &s);
2823 mlir::LogicalResult emitOMPTileDirective(const OMPTileDirective &s);
2824 mlir::LogicalResult emitOMPUnrollDirective(const OMPUnrollDirective &s);
2825 mlir::LogicalResult emitOMPFuseDirective(const OMPFuseDirective &s);
2826 mlir::LogicalResult emitOMPForDirective(const OMPForDirective &s);
2827 mlir::LogicalResult emitOMPForSimdDirective(const OMPForSimdDirective &s);
2828 mlir::LogicalResult emitOMPSectionsDirective(const OMPSectionsDirective &s);
2829 mlir::LogicalResult emitOMPSectionDirective(const OMPSectionDirective &s);
2830 mlir::LogicalResult emitOMPSingleDirective(const OMPSingleDirective &s);
2831 mlir::LogicalResult emitOMPMasterDirective(const OMPMasterDirective &s);
2832 mlir::LogicalResult emitOMPCriticalDirective(const OMPCriticalDirective &s);
2833 mlir::LogicalResult
2834 emitOMPParallelForDirective(const OMPParallelForDirective &s);
2835 mlir::LogicalResult
2836 emitOMPParallelForSimdDirective(const OMPParallelForSimdDirective &s);
2837 mlir::LogicalResult
2838 emitOMPParallelMasterDirective(const OMPParallelMasterDirective &s);
2839 mlir::LogicalResult
2840 emitOMPParallelSectionsDirective(const OMPParallelSectionsDirective &s);
2841 mlir::LogicalResult emitOMPTaskDirective(const OMPTaskDirective &s);
2842 mlir::LogicalResult emitOMPTaskgroupDirective(const OMPTaskgroupDirective &s);
2843 mlir::LogicalResult emitOMPFlushDirective(const OMPFlushDirective &s);
2844 mlir::LogicalResult emitOMPDepobjDirective(const OMPDepobjDirective &s);
2845 mlir::LogicalResult emitOMPScanDirective(const OMPScanDirective &s);
2846 mlir::LogicalResult
2847 emitOMPOrderedStandaloneDirective(const OMPOrderedStandaloneDirective &s);
2848 mlir::LogicalResult
2849 emitOMPOrderedBlockAssocDirective(const OMPOrderedBlockAssocDirective &s);
2850 mlir::LogicalResult emitOMPAtomicDirective(const OMPAtomicDirective &s);
2851 mlir::LogicalResult emitOMPTargetDirective(const OMPTargetDirective &s);
2852 mlir::LogicalResult emitOMPTeamsDirective(const OMPTeamsDirective &s);
2853 mlir::LogicalResult
2854 emitOMPCancellationPointDirective(const OMPCancellationPointDirective &s);
2855 mlir::LogicalResult emitOMPCancelDirective(const OMPCancelDirective &s);
2856 mlir::LogicalResult
2857 emitOMPTargetDataDirective(const OMPTargetDataDirective &s);
2858 mlir::LogicalResult
2859 emitOMPTargetEnterDataDirective(const OMPTargetEnterDataDirective &s);
2860 mlir::LogicalResult
2861 emitOMPTargetExitDataDirective(const OMPTargetExitDataDirective &s);
2862 mlir::LogicalResult
2863 emitOMPTargetParallelDirective(const OMPTargetParallelDirective &s);
2864 mlir::LogicalResult
2865 emitOMPTargetParallelForDirective(const OMPTargetParallelForDirective &s);
2866 mlir::LogicalResult emitOMPTaskLoopDirective(const OMPTaskLoopDirective &s);
2867 mlir::LogicalResult
2868 emitOMPTaskLoopSimdDirective(const OMPTaskLoopSimdDirective &s);
2869 mlir::LogicalResult
2870 emitOMPMaskedTaskLoopDirective(const OMPMaskedTaskLoopDirective &s);
2871 mlir::LogicalResult
2872 emitOMPMaskedTaskLoopSimdDirective(const OMPMaskedTaskLoopSimdDirective &s);
2873 mlir::LogicalResult
2874 emitOMPMasterTaskLoopDirective(const OMPMasterTaskLoopDirective &s);
2875 mlir::LogicalResult
2876 emitOMPMasterTaskLoopSimdDirective(const OMPMasterTaskLoopSimdDirective &s);
2877 mlir::LogicalResult
2878 emitOMPParallelGenericLoopDirective(const OMPParallelGenericLoopDirective &s);
2879 mlir::LogicalResult
2880 emitOMPParallelMaskedDirective(const OMPParallelMaskedDirective &s);
2881 mlir::LogicalResult emitOMPParallelMaskedTaskLoopDirective(
2883 mlir::LogicalResult emitOMPParallelMaskedTaskLoopSimdDirective(
2885 mlir::LogicalResult emitOMPParallelMasterTaskLoopDirective(
2887 mlir::LogicalResult emitOMPParallelMasterTaskLoopSimdDirective(
2889 mlir::LogicalResult
2891 mlir::LogicalResult emitOMPDistributeParallelForDirective(
2893 mlir::LogicalResult emitOMPDistributeParallelForSimdDirective(
2895 mlir::LogicalResult
2896 emitOMPDistributeSimdDirective(const OMPDistributeSimdDirective &s);
2897 mlir::LogicalResult emitOMPTargetParallelGenericLoopDirective(
2899 mlir::LogicalResult emitOMPTargetParallelForSimdDirective(
2901 mlir::LogicalResult
2902 emitOMPTargetSimdDirective(const OMPTargetSimdDirective &s);
2903 mlir::LogicalResult emitOMPTargetTeamsGenericLoopDirective(
2905 mlir::LogicalResult
2906 emitOMPTargetUpdateDirective(const OMPTargetUpdateDirective &s);
2907 mlir::LogicalResult
2908 emitOMPTeamsDistributeDirective(const OMPTeamsDistributeDirective &s);
2909 mlir::LogicalResult
2910 emitOMPTeamsDistributeSimdDirective(const OMPTeamsDistributeSimdDirective &s);
2911 mlir::LogicalResult emitOMPTeamsDistributeParallelForSimdDirective(
2913 mlir::LogicalResult emitOMPTeamsDistributeParallelForDirective(
2915 mlir::LogicalResult
2916 emitOMPTeamsGenericLoopDirective(const OMPTeamsGenericLoopDirective &s);
2917 mlir::LogicalResult
2918 emitOMPTargetTeamsDirective(const OMPTargetTeamsDirective &s);
2919 mlir::LogicalResult emitOMPTargetTeamsDistributeDirective(
2921 mlir::LogicalResult emitOMPTargetTeamsDistributeParallelForDirective(
2923 mlir::LogicalResult emitOMPTargetTeamsDistributeParallelForSimdDirective(
2925 mlir::LogicalResult emitOMPTargetTeamsDistributeSimdDirective(
2927 mlir::LogicalResult emitOMPInteropDirective(const OMPInteropDirective &s);
2928 mlir::LogicalResult emitOMPDispatchDirective(const OMPDispatchDirective &s);
2929 mlir::LogicalResult
2930 emitOMPGenericLoopDirective(const OMPGenericLoopDirective &s);
2931 mlir::LogicalResult emitOMPReverseDirective(const OMPReverseDirective &s);
2932 mlir::LogicalResult emitOMPSplitDirective(const OMPSplitDirective &s);
2933 mlir::LogicalResult
2934 emitOMPInterchangeDirective(const OMPInterchangeDirective &s);
2935 mlir::LogicalResult emitOMPFlattenDirective(const OMPFlattenDirective &s);
2936 mlir::LogicalResult emitOMPAssumeDirective(const OMPAssumeDirective &s);
2937 mlir::LogicalResult emitOMPMaskedDirective(const OMPMaskedDirective &s);
2938 mlir::LogicalResult emitOMPStripeDirective(const OMPStripeDirective &s);
2939
2940 void emitOMPThreadPrivateDecl(const OMPThreadPrivateDecl &d);
2941 void emitOMPGroupPrivateDecl(const OMPGroupPrivateDecl &d);
2942 void emitOMPCapturedExpr(const OMPCapturedExprDecl &d);
2943 void emitOMPAllocateDecl(const OMPAllocateDecl &d);
2944 void emitOMPDeclareReduction(const OMPDeclareReductionDecl &d);
2945 void emitOMPDeclareMapper(const OMPDeclareMapperDecl &d);
2946 void emitOMPRequiresDecl(const OMPRequiresDecl &d);
2947
2948 //===--------------------------------------------------------------------===//
2949 // OpenACC Emission
2950 //===--------------------------------------------------------------------===//
2951private:
2952 template <typename Op>
2953 Op emitOpenACCOp(mlir::Location start, OpenACCDirectiveKind dirKind,
2955 // Function to do the basic implementation of an operation with an Associated
2956 // Statement. Models AssociatedStmtConstruct.
2957 template <typename Op, typename TermOp>
2958 mlir::LogicalResult
2959 emitOpenACCOpAssociatedStmt(mlir::Location start, mlir::Location end,
2960 OpenACCDirectiveKind dirKind,
2962 const Stmt *associatedStmt);
2963
2964 template <typename Op, typename TermOp>
2965 mlir::LogicalResult emitOpenACCOpCombinedConstruct(
2966 mlir::Location start, mlir::Location end, OpenACCDirectiveKind dirKind,
2967 llvm::ArrayRef<const OpenACCClause *> clauses, const Stmt *loopStmt);
2968
2969 template <typename Op>
2970 void emitOpenACCClauses(Op &op, OpenACCDirectiveKind dirKind,
2972 // The second template argument doesn't need to be a template, since it should
2973 // always be an mlir::acc::LoopOp, but as this is a template anyway, we make
2974 // it a template argument as this way we can avoid including the OpenACC MLIR
2975 // headers here. We will count on linker failures/explicit instantiation to
2976 // ensure we don't mess this up, but it is only called from 1 place, and
2977 // instantiated 3x.
2978 template <typename ComputeOp, typename LoopOp>
2979 void emitOpenACCClauses(ComputeOp &op, LoopOp &loopOp,
2980 OpenACCDirectiveKind dirKind,
2982
2983 // The OpenACC LoopOp requires that we have auto, seq, or independent on all
2984 // LoopOp operations for the 'none' device type case. This function checks if
2985 // the LoopOp has one, else it updates it to have one.
2986 void updateLoopOpParallelism(mlir::acc::LoopOp &op, bool isOrphan,
2988
2989 // The OpenACC 'cache' construct actually applies to the 'loop' if present. So
2990 // keep track of the 'loop' so that we can add the cache vars to it correctly.
2991 mlir::acc::LoopOp *activeLoopOp = nullptr;
2992
2993 struct ActiveOpenACCLoopRAII {
2994 CIRGenFunction &cgf;
2995 mlir::acc::LoopOp *oldLoopOp;
2996
2997 ActiveOpenACCLoopRAII(CIRGenFunction &cgf, mlir::acc::LoopOp *newOp)
2998 : cgf(cgf), oldLoopOp(cgf.activeLoopOp) {
2999 cgf.activeLoopOp = newOp;
3000 }
3001 ~ActiveOpenACCLoopRAII() { cgf.activeLoopOp = oldLoopOp; }
3002 };
3003
3004 // Keep track of the last place we inserted a 'recipe' so that we can insert
3005 // the next one in lexical order.
3006 mlir::OpBuilder::InsertPoint lastRecipeLocation;
3007
3008public:
3009 // Helper type used to store the list of important information for a 'data'
3010 // clause variable, or a 'cache' variable reference.
3012 mlir::Location beginLoc;
3013 mlir::Value varValue;
3014 std::string name;
3015 // The type of the original variable reference: that is, after 'bounds' have
3016 // removed pointers/array types/etc. So in the case of int arr[5], and a
3017 // private(arr[1]), 'origType' is 'int', but 'baseType' is 'int[5]'.
3021 // The list of types that we found when going through the bounds, which we
3022 // can use to properly set the alloca section.
3024 };
3025
3026 // Gets the collection of info required to lower and OpenACC clause or cache
3027 // construct variable reference.
3029 // Helper function to emit the integer expressions as required by an OpenACC
3030 // clause/construct.
3031 mlir::Value emitOpenACCIntExpr(const Expr *intExpr);
3032 // Helper function to emit an integer constant as an mlir int type, used for
3033 // constants in OpenACC constructs/clauses.
3034 mlir::Value createOpenACCConstantInt(mlir::Location loc, unsigned width,
3035 int64_t value);
3036
3037 mlir::LogicalResult
3039 mlir::LogicalResult emitOpenACCLoopConstruct(const OpenACCLoopConstruct &s);
3040 mlir::LogicalResult
3042 mlir::LogicalResult emitOpenACCDataConstruct(const OpenACCDataConstruct &s);
3043 mlir::LogicalResult
3045 mlir::LogicalResult
3047 mlir::LogicalResult
3049 mlir::LogicalResult emitOpenACCWaitConstruct(const OpenACCWaitConstruct &s);
3050 mlir::LogicalResult emitOpenACCInitConstruct(const OpenACCInitConstruct &s);
3051 mlir::LogicalResult
3053 mlir::LogicalResult emitOpenACCSetConstruct(const OpenACCSetConstruct &s);
3054 mlir::LogicalResult
3056 mlir::LogicalResult
3058 mlir::LogicalResult emitOpenACCCacheConstruct(const OpenACCCacheConstruct &s);
3059
3062
3063 /// Create a temporary memory object for the given aggregate type.
3064 AggValueSlot createAggTemp(QualType ty, mlir::Location loc,
3065 const Twine &name = "tmp",
3066 Address *alloca = nullptr) {
3068 return AggValueSlot::forAddr(
3069 createMemTemp(ty, loc, name, alloca), ty.getQualifiers(),
3072 }
3073
3074private:
3075 QualType getVarArgType(const Expr *arg);
3076
3077 bool shouldEmitLifetimeMarkers = false;
3078 /// Set when the current function has a goto/switch that may bypass a local's
3079 /// init; lifetime markers are then suppressed. See functionMightHaveBypass.
3080 bool fnHasBypassStmt = false;
3081
3082 bool shouldEmitLifetimeMarkersForAutoVar() const {
3083 return shouldEmitLifetimeMarkers && !fnHasBypassStmt;
3084 }
3085
3086 class InlinedInheritingConstructorScope {
3087 public:
3088 InlinedInheritingConstructorScope(CIRGenFunction &cgf, GlobalDecl gd)
3089 : cgf(cgf), oldCurGD(cgf.curGD), oldCurFuncDecl(cgf.curFuncDecl),
3090 oldCurCodeDecl(cgf.curCodeDecl),
3091 oldCxxabiThisDecl(cgf.cxxabiThisDecl),
3092 oldCxxThisValue(cgf.cxxThisValue),
3093 oldCxxabiThisAlignment(cgf.cxxabiThisAlignment),
3094 oldCxxThisAlignment(cgf.cxxThisAlignment),
3095 oldReturnValue(cgf.returnValue), oldFnRetTy(cgf.fnRetTy),
3096 oldCxxInheritedCtorInitExprArgs(
3097 std::move(cgf.cxxInheritedCtorInitExprArgs)) {
3098 cgf.curGD = gd;
3099 cgf.curFuncDecl = cast<CXXConstructorDecl>(gd.getDecl());
3100 cgf.curCodeDecl = cgf.curFuncDecl;
3101 cgf.cxxabiThisDecl = nullptr;
3102 cgf.cxxabiThisValue = nullptr;
3103 cgf.cxxThisValue = nullptr;
3104 cgf.cxxThisAlignment = CharUnits();
3105 cgf.cxxabiThisAlignment = CharUnits();
3106 cgf.returnValue = Address::invalid();
3107 cgf.fnRetTy = QualType();
3108 cgf.cxxInheritedCtorInitExprArgs.clear();
3109 // FIXME: at one point when we want to call one of these, we'll need
3110 // CXXInheritedCtorInitExprArgs here too.
3111 }
3112 ~InlinedInheritingConstructorScope() {
3113 cgf.curGD = oldCurGD;
3114 cgf.curFuncDecl = oldCurFuncDecl;
3115 cgf.curCodeDecl = oldCurCodeDecl;
3116 cgf.cxxabiThisDecl = oldCxxabiThisDecl;
3117 cgf.cxxabiThisValue = oldCxxabiThisValue;
3118 cgf.cxxThisValue = oldCxxThisValue;
3119 cgf.cxxThisAlignment = oldCxxThisAlignment;
3120 cgf.cxxabiThisAlignment = oldCxxabiThisAlignment;
3121 cgf.returnValue = oldReturnValue;
3122 cgf.fnRetTy = oldFnRetTy;
3123 cgf.cxxInheritedCtorInitExprArgs =
3124 std::move(oldCxxInheritedCtorInitExprArgs);
3125 }
3126
3127 private:
3128 CIRGenFunction &cgf;
3129 GlobalDecl oldCurGD;
3130 const Decl *oldCurFuncDecl;
3131 const Decl *oldCurCodeDecl;
3132 ImplicitParamDecl *oldCxxabiThisDecl;
3133 mlir::Value oldCxxabiThisValue;
3134 mlir::Value oldCxxThisValue;
3135 clang::CharUnits oldCxxabiThisAlignment;
3136 clang::CharUnits oldCxxThisAlignment;
3137 Address oldReturnValue;
3138 QualType oldFnRetTy;
3139 CallArgList oldCxxInheritedCtorInitExprArgs;
3140 };
3141};
3142
3143} // namespace clang::CIRGen
3144
3145#endif
Defines the clang::ASTContext interface.
static void emitOMPDistributeDirective(const OMPLoopDirective &S, CodeGenFunction &CGF, CodeGenModule &CGM)
static void emitOMPForDirective(const OMPLoopDirective &S, CodeGenFunction &CGF, CodeGenModule &CGM, bool HasCancel)
static void emitOMPSimdDirective(const OMPLoopDirective &S, CodeGenFunction &CGF, CodeGenModule &CGM)
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, Address expectedResult, Expr *isWeakExpr, Expr *failureOrderExpr, int64_t size, cir::MemOrder order, cir::SyncScopeKind scope)
Defines the clang::Expr interface and subclasses for C++ expressions.
Defines some OpenACC-specific enums and functions.
*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 atomic' directive.
This represents 'pragma omp barrier' directive.
This represents 'pragma omp cancel' directive.
This represents 'pragma omp cancellation point' directive.
This represents 'pragma omp critical' directive.
This represents 'pragma omp depobj' 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 flatten' loop transformation directive.
This represents 'pragma omp flush' directive.
This represents 'pragma omp for' directive.
This represents 'pragma omp for simd' 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' directive.
This represents 'pragma omp master taskloop' directive.
This represents 'pragma omp master taskloop simd' directive.
This represents 'pragma omp metadirective' directive.
This represents block-associated 'pragma omp ordered' directive.
This represents standalone 'pragma omp ordered' directive.
This represents 'pragma omp parallel for' directive.
This represents 'pragma omp parallel for simd' directive.
This represents 'pragma omp parallel loop' directive.
This represents 'pragma omp parallel masked' directive.
This represents 'pragma omp parallel masked taskloop' directive.
This represents 'pragma omp parallel masked taskloop simd' directive.
This represents 'pragma omp parallel master' directive.
This represents 'pragma omp parallel master taskloop' directive.
This represents 'pragma omp parallel master taskloop simd' directive.
This represents 'pragma omp parallel sections' directive.
Represents the 'pragma omp reverse' loop transformation directive.
This represents 'pragma omp scan' directive.
This represents 'pragma omp scope' directive.
This represents 'pragma omp section' directive.
This represents 'pragma omp sections' directive.
This represents 'pragma omp simd' directive.
This represents 'pragma omp single' 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 task' directive.
This represents 'pragma omp taskloop' directive.
This represents 'pragma omp taskloop simd' directive.
This represents 'pragma omp taskgroup' directive.
This represents 'pragma omp taskwait' directive.
This represents 'pragma omp taskyield' 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:245
AbstractConditionalOperator - An abstract base class for ConditionalOperator and BinaryConditionalOpe...
Definition Expr.h:4401
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Definition Expr.h:2769
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition TypeBase.h:3820
AsmStmt is the base class for GCCAsmStmt and MSAsmStmt.
Definition Stmt.h:3289
AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*, __atomic_load,...
Definition Expr.h:6982
Represents an attribute applied to a statement.
Definition Stmt.h:2215
BinaryConditionalOperator - The GNU extension to the conditional operator which allows the middle ope...
Definition Expr.h:4501
OpaqueValueExpr * getOpaqueValue() const
getOpaqueValue - Return the opaque value placeholder.
Definition Expr.h:4539
Expr * getCommon() const
getCommon - Return the common expression, written to the left of the condition.
Definition Expr.h:4536
A builtin binary operation expression such as "x + y" or "x <= y".
Definition Expr.h:4086
BreakStmt - This represents a break.
Definition Stmt.h:3147
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)
Captures cleanups for variables whose lifetime ends in a region owned by an enclosing op rather than ...
CapturedCleanups(CIRGenFunction &cgf, bool active)
void emitIntoCleanupRegion(mlir::Location loc)
Emit the captured cleanups into the current insertion point, which must be inside the owning op's cle...
An object to manage conditionally-evaluated expressions.
void advanceInsertPoint(mlir::Operation *op)
Records op as the last operation emitted at the pre-conditional insertion point, so that a later emis...
mlir::OpBuilder::InsertPoint getInsertPoint() const
Returns the insertion point which will be executed prior to each evaluation of the conditional code.
ConditionalEvaluation(CIRGenFunction &cgf, mlir::Location loc)
loc is the location of the conditional expression.
static ConstantEmission forReference(mlir::TypedAttr c)
static ConstantEmission forValue(mlir::TypedAttr c)
LValue getReferenceLValue(CIRGenFunction &cgf, Expr *refExpr) const
DeclMapRevertingRAII(CIRGenFunction &cgf, const VarDecl *vd)
FieldConstructionScope(CIRGenFunction &cgf, Address thisAddr)
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, SourceRange value)
static bool isConstructorDelegationValid(const clang::CXXConstructorDecl *ctor)
Checks whether the given constructor is a valid subject for the complete-to-base constructor delegati...
static bool hasScalarEvaluationKind(clang::QualType type)
void emitFunctionProlog(const FunctionArgList &args, mlir::Block *entryBB, const FunctionDecl *fd, SourceLocation bodyBeginLoc)
Emit the function prologue: initialize the return value of an implicit-return-zero function and decla...
void emitOpenACCRoutine(const OpenACCRoutineDecl &d)
void emitLambdaDelegatingInvokeBody(const CXXMethodDecl *md)
mlir::Value emitComplexToScalarConversion(mlir::Value src, QualType srcTy, QualType dstTy, SourceLocation loc)
Emit a conversion from the specified complex type to the specified destination type,...
void emitCallArgs(CallArgList &args, PrototypeWrapper prototype, llvm::iterator_range< clang::CallExpr::const_arg_iterator > argRange, AbstractCallee callee=AbstractCallee(), unsigned paramsToSkip=0)
mlir::Type convertType(clang::QualType t)
cir::GlobalOp addInitializerToStaticVarDecl(const VarDecl &d, cir::GlobalOp gv, cir::GetGlobalOp gvAddr)
Add the initializer for 'd' to the global variable that has already been created for it.
LValue emitCXXBindTemporaryLValue(const CXXBindTemporaryExpr *e)
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)
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.
mlir::LogicalResult emitOpenACCWaitConstruct(const OpenACCWaitConstruct &s)
cir::FuncOp generateCode(clang::GlobalDecl gd, cir::FuncOp fn, cir::FuncType funcType)
llvm::SmallVector< PendingCleanupEntry > lifetimeExtendedCleanupStack
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
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
void emitCapturedCleanups(EHScopeStack::stable_iterator depth, mlir::Location loc)
Emit the captured cleanups (those pushed above depth while EHScopeStack was capturing cleanups) at th...
cir::AllocaOp createTempAlloca(mlir::Type ty, mlir::Location loc, const Twine &name="tmp", mlir::Value arraySize=nullptr, bool insertIntoFnEntryBlock=false)
This creates an alloca and inserts it into the entry block if ArraySize is nullptr,...
void emitTrap(mlir::Location loc, bool createNewBlock)
Emit a trap instruction, which is used to abort the program in an abnormal way, usually for debugging...
void emitForwardingCallToLambda(const CXXMethodDecl *lambdaCallOperator, CallArgList &callArgs)
mlir::Block * getCurFunctionEntryBlock()
RValue emitCXXMemberCallExpr(const clang::CXXMemberCallExpr *e, ReturnValueSlot returnValue)
mlir::LogicalResult emitOpenACCUpdateConstruct(const OpenACCUpdateConstruct &s)
RValue emitCXXMemberPointerCallExpr(const CXXMemberCallExpr *ce, ReturnValueSlot returnValue)
mlir::Value emitX86CpuIs(const CallExpr *expr)
LValue emitLValueForBitField(LValue base, const FieldDecl *field)
mlir::LogicalResult emitIfOnBoolExpr(const clang::Expr *cond, const clang::Stmt *thenS, const clang::Stmt *elseS)
Emit an if on a boolean condition to the specified blocks.
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)
cir::CoroAllocOp emitCoroAllocBuiltinCall(const CallExpr *e)
Address cxxDefaultInitExprThis
The value of 'this' to sue when evaluating CXXDefaultInitExprs within this expression.
cir::IfOp emitIfOnBoolValue(mlir::Value condV, mlir::Location loc, BuilderCallbackRef thenBuilder, mlir::Location thenLoc, BuilderCallbackRef elseBuilder, std::optional< mlir::Location > elseLoc={})
Build the cir.if for an already-emitted condition value.
void emitStaticVarDecl(const VarDecl &d, cir::GlobalLinkageKind linkage)
mlir::Value emitComplexExpr(const Expr *e)
Emit the computation of the specified expression of complex type, returning the result.
void setBeforeOutermostConditional(mlir::Value value, Address addr)
mlir::LogicalResult emitOpenACCCacheConstruct(const OpenACCCacheConstruct &s)
mlir::Value loadCXXThis()
Load the value for 'this'.
LValue makeNaturalAlignPointeeAddrLValue(mlir::Value v, clang::QualType t)
Given a value of type T* that may not be to a complete object, construct an l-vlaue withi the natural...
RValue emitCallExpr(const clang::CallExpr *e, ReturnValueSlot returnValue=ReturnValueSlot())
void emitDeleteCall(const FunctionDecl *deleteFD, mlir::Value ptr, QualType deleteTy)
LValue emitMemberExpr(const MemberExpr *e)
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 emitCXXForRangeStmt(const CXXForRangeStmt &s, llvm::ArrayRef< const Attr * > attrs)
cir::CoroNoopOp emitCoroNoopBuiltinCall(const CallExpr *e)
bool insertionPointIsReachable() const
True if code emitted at the builder's insertion point can be reached.
LValue emitLValueForLambdaField(const FieldDecl *field)
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.
cir::CoroSuspendOp emitCoroSuspendBuiltinCall(const CallExpr *e)
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,...
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.
void emitLifetimeEndOp(mlir::Location loc, mlir::Value addr)
Address getAsNaturalAddressOf(Address addr, QualType pointeeTy)
void pushCleanupAndDeferDeactivation(CleanupKind kind, As... a)
Push a cleanup and record it for deferred deactivation.
cir::TryOp ehSpecTryOp
The cir.try wrapping a function whose exception specification has to be enforced.
LValue emitComplexCompoundAssignmentLValue(const CompoundAssignOperator *e)
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.
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 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 emitAggregateStore(mlir::Value value, Address dest)
mlir::LogicalResult emitReturnStmt(const clang::ReturnStmt &s)
LValue emitLoadOfReferenceLValue(Address refAddr, mlir::Location loc, QualType refTy, AlignmentSource source)
cir::CoroBeginOp emitCoroBeginBuiltinCall(const CallExpr *e)
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.
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.
void emitLoopConditionVariable(const clang::VarDecl &d, CapturedCleanups &condCleanup, llvm::ArrayRef< QualType > extendedTemporaries)
Emit a loop's condition-variable declaration.
mlir::Value emitArrayLength(const clang::ArrayType *arrayType, QualType &baseType, Address &addr)
Computes the length of an array in elements, as well as the base element type and a properly-typed fi...
void emitNullInitialization(mlir::Location loc, Address destPtr, QualType ty)
mlir::LogicalResult emitOpenACCSetConstruct(const OpenACCSetConstruct &s)
mlir::Value performAddrSpaceCast(mlir::Value v, mlir::Type destTy) const
RValue emitReferenceBindingToExpr(const Expr *e)
Emits a reference binding to the passed in expression.
llvm::SmallVector< DeferredDeactivateCleanup > deferredDeactivationCleanupStack
VPtrsVector getVTablePointers(const clang::CXXRecordDecl *vtableClass)
const TargetCIRGenInfo & getTargetHooks() const
mlir::LogicalResult emitSwitchStmt(const clang::SwitchStmt &s)
RValue emitCoyieldExpr(const CoyieldExpr &e, AggValueSlot aggSlot=AggValueSlot::ignored(), bool ignoreResult=false)
cir::CoroFreeOp emitCoroFreeBuiltin(const CallExpr *e)
mlir::Value evaluateOrEmitBuiltinObjectSize(const clang::Expr *e, unsigned type, cir::IntType resType, mlir::Value emittedE, bool isDynamic)
mlir::Value emitX86CpuInit(mlir::Location loc)
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)
void emitScalarInit(const clang::Expr *init, LValue lvalue, bool capturedByInit=false)
llvm::ScopedHashTableScope< const clang::Decl *, mlir::Value > SymTableScopeTy
OpenACCDataOperandInfo getOpenACCDataOperandInfo(const Expr *e)
CleanupKind getCleanupKind(QualType::DestructionKind kind)
clang::CharUnits cxxabiThisAlignment
void checkTargetFeatures(const clang::CallExpr *e, const clang::FunctionDecl *targetDecl)
Emit a diagnostic if the target features required by targetDecl are not available in the calling func...
mlir::Value emitX86CpuSupports(const CallExpr *expr)
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)
AggValueSlot::Overlap_t getOverlapForFieldInit(const FieldDecl *fd)
mlir::LogicalResult emitSimpleStmt(const clang::Stmt *s, bool useCurrentScope)
mlir::Operation * curFn
The current function or global initializer that is generated code for.
mlir::LogicalResult emitAsmStmt(const clang::AsmStmt &s)
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::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)
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.
mlir::Value emitDevicePrintfCallExpr(const CallExpr *expr)
Emit a device-side printf call for GPU targets.
llvm::SmallVector< PendingCleanupEntry > deferredConditionalCleanupStack
Cleanups for temporaries constructed inside a conditional.
llvm::SmallVector< ConditionalCleanupScope > conditionalCleanupScopes
void emitNewArrayInitializer(const CXXNewExpr *e, QualType elementType, mlir::Type elementTy, Address beginPtr, mlir::Value numElements, mlir::Value allocSizeWithoutCookie)
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.
cir::FastMathFlagsAttr getFastMathFlagsAttr(cir::FastMathFlags fastMathFlags)
Create a CIR fast-math attribute from the specified flags.
RValue emitLoadOfExtVectorElementLValue(LValue lv)
mlir::Value emitCXXTypeidExpr(const CXXTypeidExpr *e)
mlir::Type convertTypeForMem(QualType t)
clang::QualType buildFunctionArgList(clang::GlobalDecl gd, FunctionArgList &args)
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::LogicalResult emitCXXTryStmt(const clang::CXXTryStmt &s, cxxTryBodyEmitter &bodyCallback, bool isFnTryBlock=false)
mlir::Value createDummyValue(mlir::Location loc, clang::QualType qt)
mlir::LogicalResult emitAttributedStmt(const AttributedStmt &s)
cir::FastMathFlags getCurrentFastMathFlags() const
Convert the active Clang floating-point options to CIR fast-math flags.
void emitCXXConstructExpr(const clang::CXXConstructExpr *e, AggValueSlot dest)
mlir::Value emitLoadOfComplex(LValue src, SourceLocation loc)
Load a complex number from the specified l-value.
cir::CoroPromiseOp emitCoroPromiseBuiltinCall(const CallExpr *e)
LValue emitAggExprToLValue(const Expr *e)
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)
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.
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)
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)
RValue emitAnyExprToTemp(const clang::Expr *e)
Similarly to emitAnyExpr(), however, the result will always be accessible even if no aggregate locati...
void finishFunction(SourceLocation endLoc)
mlir::LogicalResult emitOpenACCShutdownConstruct(const OpenACCShutdownConstruct &s)
mlir::LogicalResult emitFunctionBody(const clang::Stmt *body)
mlir::LogicalResult emitBreakStmt(const clang::BreakStmt &s)
void initFullExprCleanupWithFlag(Address activeFlag)
cir::CoroDestroyOp emitCoroDestroyBuiltinCall(const CallExpr *e)
mlir::LogicalResult emitIndirectGotoStmt(const IndirectGotoStmt &s)
mlir::Value emitTernaryOnBoolExpr(const clang::Expr *cond, mlir::Location loc, const clang::Stmt *thenS, const clang::Stmt *elseS)
void emitCallAndReturnForThunk(cir::FuncOp callee, SourceRange fnLoc, const ThunkInfo *thunk, bool isUnprototyped)
Emit the call and return for a thunk function.
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
LValue emitUnaryOpLValue(const clang::UnaryOperator *e)
void emitReturnOfRValue(mlir::Location loc, RValue rv, QualType ty)
LValue emitMatrixSubscriptExpr(const MatrixSubscriptExpr *e)
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)
LValue emitComplexAssignmentLValue(const BinaryOperator *e)
void emitCallArg(CallArgList &args, const clang::Expr *e, clang::QualType argType)
bool checkIfLoopMustProgress(const clang::Expr *controllingExpression, bool hasEmptyBody)
cir::CoroEndOp emitCoroEndBuiltinCall(const CallExpr *e)
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.
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)
LValue emitCallExprLValue(const clang::CallExpr *e)
bool haveInsertPoint() const
True if an insertion point is defined.
llvm::SmallVector< mlir::Type, 2 > condTypeStack
The type of the condition for the emitting switch statement.
RValue emitBuiltinWithOneOverloadedType(const CallExpr *e, llvm::StringRef intrinName, mlir::Type resultType={})
Emit a simple LLVM intrinsic that takes N scalar arguments.
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")
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 loadThisForDtorDelete(const CXXDestructorDecl *dd)
Return the pointer to pass to the operator delete of the given destructor, converted to the type of i...
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)
const LifetimeExtensionCapture * lifetimeExtensionCapture
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)
void emitAutoVarDecl(const clang::VarDecl &d)
Emit code and set up symbol table for a variable declaration with auto, register, or no storage class...
cir::GetGlobalOp createGetCpuModel(mlir::Location loc)
void pushLifetimeExtendedDestroy(CleanupKind kind, Address addr, QualType type, Destroyer *destroyer, bool useEHCleanupForArray, const clang::ValueDecl *extendingDecl)
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::Value emitAtomicCmpXchg(const clang::CallExpr *expr, bool returnBool, cir::MemOrder successOrder=cir::MemOrder::SequentiallyConsistent, cir::MemOrder failureOrder=cir::MemOrder::SequentiallyConsistent, cir::SyncScopeKind scope=cir::SyncScopeKind::System)
Emit cir.atomic.cmpxchg.
CIRGenBuilderTy & getBuilder()
void emitVAStart(mlir::Value vaList)
Emits the start of a CIR variable-argument operation (cir.va_start)
cir::VectorType getSVEType(const SVETypeFlags &typeFlags)
bool didCallStackSave
Whether a cir.stacksave operation has been added.
void emitDecl(const clang::Decl &d, bool evaluateConditionDecl=false)
LValue emitBinaryOperatorLValue(const BinaryOperator *e)
mlir::Value emitOpenACCIntExpr(const Expr *intExpr)
Address getAddrOfBitFieldStorage(LValue base, const clang::FieldDecl *field, mlir::Type fieldType, unsigned index)
AggValueSlot::Overlap_t getOverlapForBaseInit(const CXXRecordDecl *rd, const CXXRecordDecl *baseRD, bool isVirtual)
Determine whether a base class initialization may overlap some other object.
cir::FuncType getIntrinsicType(llvm::Intrinsic::ID id, llvm::ArrayRef< mlir::Type > overloadTys={})
Return the CIR signature of the LLVM intrinsic id, resolving its overloaded types to overloadTys.
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.
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)
RValue emitCall(const CIRGenFunctionInfo &funcInfo, const CIRGenCallee &callee, ReturnValueSlot returnValue, const CallArgList &args, bool isMustTail, cir::CIRCallOpInterface *callOrTryCall=nullptr)
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.
std::optional< SourceRange > currSrcLoc
Use to track source locations across nested visitor traversals.
LValue emitCastLValue(const CastExpr *e)
Casts are never lvalues unless that cast is to a reference type.
LValue emitCXXTypeidLValue(const CXXTypeidExpr *e)
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)
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)
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.
std::optional< mlir::Value > emitNVPTXBuiltinExpr(unsigned builtinID, const CallExpr *expr)
Emit a call to an NVPTX builtin function.
static void eraseEmptyAndUnusedBlocks(cir::FuncOp func)
Remove leftover empty and unreachable blocks from an emitted function.
llvm::DenseMap< const clang::ValueDecl *, clang::FieldDecl * > lambdaCaptureFields
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.
bool emitLifetimeStartOp(mlir::Location loc, mlir::Value addr)
RValue emitCall(const CIRGenFunctionInfo &funcInfo, const CIRGenCallee &callee, ReturnValueSlot returnValue, const CallArgList &args, cir::CIRCallOpInterface *callOp, bool isMustTail, SourceRange clangLoc)
mlir::Value emitAlignmentAssumption(mlir::Value ptrValue, QualType ty, SourceLocation loc, SourceLocation assumptionLoc, int64_t alignment, mlir::Value offsetValue=nullptr)
mlir::LogicalResult emitCaseDefaultCascade(const T *stmt, mlir::Type condType, mlir::ArrayAttr value, cir::CaseOpKind kind, bool buildingTopLevelCase)
void emitCXXThrowExpr(const CXXThrowExpr *e)
LValue makeAddrLValue(Address addr, QualType ty, AlignmentSource source=AlignmentSource::Type)
int64_t getAccessedFieldNo(unsigned idx, mlir::ArrayAttr elts)
LValue emitPredefinedLValue(const PredefinedExpr *e)
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.
void emitCXXDestructorCall(const CXXDestructorDecl *dd, CXXDtorType type, bool forVirtualBase, bool delegating, Address thisAddr, QualType thisTy)
llvm::SmallVector< VPtr, 4 > VPtrsVector
cir::CoroSizeOp emitCoroSizeBuiltinCall(const CallExpr *e)
void emitLambdaStaticInvokeBody(const CXXMethodDecl *md)
bool sawAsmBlock
Whether or not a Microsoft-style asm block has been processed within this fuction.
void emitEndEHSpec(const clang::Decl *d)
Close the cir.try opened by emitStartEHSpec.
mlir::LogicalResult emitDeclStmt(const clang::DeclStmt &s)
cir::GetGlobalOp createGetCpuFeatures2(mlir::Location loc)
cir::CleanupScopeOp currentFullExprCleanupScope
The cir.cleanup.scope of the innermost FullExprCleanupScope that materialized one,...
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)
cir::CoroDoneOp emitCoroDoneBuiltinCall(const CallExpr *e)
mlir::LogicalResult emitWhileStmt(const clang::WhileStmt &s)
cir::CoroResumeOp emitCoroResumeBuiltinCall(const CallExpr *e)
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.
cir::CoroAlignOp emitCoroAlignBuiltinCall(const CallExpr *e)
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.
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)
cir::CoroIdOp emitCoroIDBuiltinCall(const CallExpr *e)
void terminateStructuredRegionBody(mlir::Region &r, mlir::Location loc)
LValue emitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *e)
LValue emitExtVectorElementExpr(const ExtVectorElementExpr *e)
bool inEHSpecTerminateScope()
Whether the wrapper opened by emitStartEHSpec is a terminate scope, whose handler calls std::terminat...
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 emitSYCLKernelCaller(const clang::OutlinedFunctionDecl *outlinedFnDecl, cir::FuncOp funcOp, cir::FuncType funcType, FunctionArgList &args)
void emitStartEHSpec(const clang::Decl *d)
Wrap the function body in a cir.try that enforces the exception specification of d: a filter handler ...
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)
bool inAlwaysInlineAttributedStmt
True if the current statement has always_inline attribute.
bool inNoInlineAttributedStmt
True if the current statement has noinline attribute.
void emitStoreThroughLValue(RValue src, LValue dst, bool isInit=false)
Store the specified rvalue into the specified lvalue, where both are guaranteed to the have the same ...
bool isLValueSuitableForInlineAtomic(LValue lv)
An LValue is a candidate for having its loads and stores be made atomic if we are operating under /vo...
static llvm::SmallVector< QualType, 2 > getLifetimeExtendedTemporariesWithDestructor(const clang::VarDecl &d)
The types of the temporaries with a destructor that the initializer of the variable d,...
mlir::LogicalResult emitStmt(const clang::Stmt *s, bool useCurrentScope, llvm::ArrayRef< const Attr * > attrs={})
RValue getOrCreateOpaqueRValueMapping(const OpaqueValueExpr *e)
Given an opaque value expression, return its RValue mapping if it exists, otherwise create one.
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 emitCompoundStmtWithoutScope(const clang::CompoundStmt &s, Address *lastValue=nullptr, AggValueSlot slot=AggValueSlot::ignored())
mlir::LogicalResult emitOpenACCExitDataConstruct(const OpenACCExitDataConstruct &s)
void generateThunk(cir::FuncOp fn, SourceRange fnLoc, const CIRGenFunctionInfo &fnInfo, GlobalDecl gd, const ThunkInfo &thunk, bool isUnprototyped)
Generate code for a thunk function.
mlir::LogicalResult emitSYCLKernelCallStmt(const SYCLKernelCallStmt &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)
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)
LValue emitCXXConstructLValue(const CXXConstructExpr *e)
void finishThunk()
Finish generating a thunk function.
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:51
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:239
Represents binding an expression to a temporary.
Definition ExprCXX.h:1498
CXXCatchStmt - This represents a C++ catch block.
Definition StmtCXX.h:29
Represents a call to a C++ constructor.
Definition ExprCXX.h:1553
Represents a C++ constructor within a class.
Definition DeclCXX.h:2642
Represents a C++ base or member initializer.
Definition DeclCXX.h:2407
A default argument (C++ [dcl.fct.default]).
Definition ExprCXX.h:1275
A use of a default initializer in a constructor or in aggregate initialization.
Definition ExprCXX.h:1382
Represents a delete expression for memory deallocation and destructor calls, e.g.
Definition ExprCXX.h:2631
Represents a C++ destructor within a class.
Definition DeclCXX.h:2907
A C++ dynamic_cast expression (C++ [expr.dynamic.cast]).
Definition ExprCXX.h:486
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:1756
Represents a call to a member function that may be written either with member call syntax (e....
Definition ExprCXX.h:184
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2150
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)".
Definition ExprCXX.h:2360
A call to an overloaded operator written using operator syntax.
Definition ExprCXX.h:86
Represents a C++ pseudo-destructor (C++ [expr.pseudo]).
Definition ExprCXX.h:2750
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
Represents a C++ temporary.
Definition ExprCXX.h:1464
A C++ throw-expression (C++ [except.throw]).
Definition ExprCXX.h:1213
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:853
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2991
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition Expr.h:3195
CaseStmt - Represent a case statement.
Definition Stmt.h:1932
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Definition Expr.h:3724
This is an opaque type for sizes expressed in character units.
Definition CharUnits.h:38
bool isZero() const
Test whether the quantity equals zero.
Definition CharUnits.h:101
llvm::Align getAsAlign() const
Returns Quantity as a valid llvm::Align, Beware llvm::Align assumes power of two 8-bit bytes.
Definition CharUnits.h:159
CompoundAssignOperator - For compound assignments (e.g.
Definition Expr.h:4348
CompoundLiteralExpr - [C99 6.5.2.5].
Definition Expr.h:3653
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition Stmt.h:1752
ContinueStmt - This represents a continue.
Definition Stmt.h:3131
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:1294
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition Stmt.h:1643
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
DoStmt - This represents a 'do/while' stmt.
Definition Stmt.h:2844
This represents one expression.
Definition Expr.h:113
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:145
ExtVectorElementExpr - This represents access to specific elements of a vector, and may occur on the ...
Definition Expr.h:6664
Represents a member of a struct/union/class.
Definition Decl.h:3299
ForStmt - This represents a 'for (init;cond;inc)' stmt.
Definition Stmt.h:2900
Represents a function declaration or definition.
Definition Decl.h:2059
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5416
GlobalDecl - represents a global declaration.
Definition GlobalDecl.h:60
const Decl * getDecl() const
Definition GlobalDecl.h:115
GotoStmt - This represents a direct goto.
Definition Stmt.h:2981
IndirectGotoStmt - This represents an indirect goto.
Definition Stmt.h:3020
Describes an C or C++ initializer list.
Definition Expr.h:5356
FPExceptionModeKind
Possible floating point exception behavior.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
MatrixSubscriptExpr - Matrix subscript expression for the MatrixType extension.
Definition Expr.h:2913
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition Expr.h:3412
A pointer to member type per C++ 8.3.3 - Pointers to members.
Definition TypeBase.h:3751
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:1202
Expr * getSourceExpr() const
The source expression of an opaque value expression is the expression which originally generated the ...
Definition Expr.h:1252
Represents a parameter to a function.
Definition Decl.h:1820
[C99 6.4.2.2] - A predefined identifier such as func.
Definition Expr.h:2053
PseudoObjectExpr - An expression which accesses a pseudo-object l-value.
Definition Expr.h:6858
A (possibly-)qualified type.
Definition TypeBase.h:938
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition TypeBase.h:8486
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:85
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:228
Represents a declaration of a type.
Definition Decl.h:3652
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:2292
Represents a call to the builtin function __builtin_va_arg.
Definition Expr.h:5005
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition Decl.h:713
Represents a variable declaration or definition.
Definition Decl.h:933
Represents a C array with a specified size that is not an integer-constant-expression.
Definition TypeBase.h:4064
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.
@ NormalCleanup
Denotes a cleanup that should run when a scope is exited using normal control flow (falling off the e...
bool checkIfLoopMustProgress(const LangOptions &LangOpts, const CodeGenOptions &CGOpts, ASTContext &Ctx, const Expr *ControllingExpression, bool HasEmptyBody, llvm::function_ref< void()> RemoveMustProgress)
Returns true if a loop must make progress, which means the mustprogress attribute can be added to it.
Definition StmtUtils.cpp:15
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
std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl
All declarations that can appear in a module declaration.
Top level wrappers for InstallAPI frontend operations.
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
CXXCtorType
C++ constructor types.
Definition ABI.h:24
OpenACCDirectiveKind
QualType pointeeType(QualType T)
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 useLifetimeMarkers
True if lifetime op should be used.
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.
One record per cir.cleanup.scope opened by a ConditionalEvaluation, as described above.
size_t deferredCleanupStackSize
The size of deferredConditionalCleanupStack when this scope was opened.
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)
Set by emitLoopConditionVariable while it emits the initializer of a loop condition variable that lif...
A cleanup whose destructor call is not emitted where the cleanup is registered.
CapturedCleanups * capturedBy
If set, the cleanup is captured by this owner instead of opening a cir.cleanup.scope when it is pushe...
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