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