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