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 entry that will be promoted onto the EH scope stack at a later
131 /// point. Used by both the lifetime-extended cleanup stack (promoted when
132 /// the enclosing scope exits) and the deferred conditional cleanup stack
133 /// (promoted at the enclosing full-expression level).
134 ///
135 /// Currently only DestroyObject cleanups use this. When other cleanup types
136 /// are needed (e.g., CallLifetimeEnd), this struct can be extended with a
137 /// std::variant of cleanup data types.
145
147
149
150 /// A cleanup that was pushed to the EH stack but whose deactivation is
151 /// deferred until the enclosing CleanupDeactivationScope exits. Used to
152 /// protect partially-constructed aggregates (e.g. lambda captures) so that
153 /// already-initialized sub-objects are destroyed if a later initializer
154 /// throws, while avoiding double-destruction after full construction.
160
161 /// Scope that deactivates all enclosed deferred cleanups on exit.
162 /// Mirrors CodeGenFunction::CleanupDeactivationScope in classic codegen.
166 bool deactivated = false;
167
171
173 assert(!deactivated && "Deactivating already deactivated scope");
174 auto &stack = cgf.deferredDeactivationCleanupStack;
175 for (size_t i = stack.size(); i > oldDeactivateCleanupStackSize; i--) {
176 cgf.deactivateCleanupBlock(stack[i - 1].cleanup,
177 stack[i - 1].dominatingIP);
178 stack[i - 1].dominatingIP->erase();
179 }
180 stack.resize(oldDeactivateCleanupStackSize);
181 deactivated = true;
182 }
183
188 };
189
191
192 /// If a ParmVarDecl had the pass_object_size attribute, this will contain a
193 /// mapping from said ParmVarDecl to its implicit "object_size" parameter.
194 llvm::SmallDenseMap<const ParmVarDecl *, const ImplicitParamDecl *>
196
197 /// A mapping from NRVO variables to the flags used to indicate
198 /// when the NRVO has been applied to this variable.
199 llvm::DenseMap<const VarDecl *, mlir::Value> nrvoFlags;
200
201 llvm::DenseMap<const clang::ValueDecl *, clang::FieldDecl *>
204
205 /// CXXThisDecl - When generating code for a C++ member function,
206 /// this will hold the implicit 'this' declaration.
208 mlir::Value cxxabiThisValue = nullptr;
209 mlir::Value cxxThisValue = nullptr;
212
213 /// When generating code for a constructor or destructor, this will hold the
214 /// implicit argument (e.g. VTT).
217
218 /// The value of 'this' to sue when evaluating CXXDefaultInitExprs within this
219 /// expression.
221
222 /// The values of function arguments to use when evaluating
223 /// CXXInheritedCtorInitExprs within this context.
225
226 /// The current array initialization index when evaluating an
227 /// ArrayInitIndexExpr within an ArrayInitLoopExpr.
228 mlir::Value arrayInitIndex = nullptr;
229
230 // Holds the Decl for the current outermost non-closure context
231 const clang::Decl *curFuncDecl = nullptr;
232 /// This is the inner-most code context, which includes blocks.
233 const clang::Decl *curCodeDecl = nullptr;
236
237 /// The current function or global initializer that is generated code for.
238 /// This is usually a cir::FuncOp, but it can also be a cir::GlobalOp for
239 /// global initializers.
240 mlir::Operation *curFn = nullptr;
241
242 /// While the initializer of a variable with static storage duration is being
243 /// emitted, the region that destructors registered by that initializer belong
244 /// in: the cir.global's own dtor region for a namespace-scope variable, and
245 /// the enclosing cir.local_init's for a function-local static, which has to
246 /// be destroyed in-function under its guard. Null outside such an
247 /// initializer.
248 mlir::Region *curStaticVarDtorRegion = nullptr;
249
250 /// Save Parameter Decl for coroutine.
252
253 using DeclMapTy = llvm::DenseMap<const clang::Decl *, Address>;
254 /// This keeps track of the CIR allocas or globals for local C
255 /// declarations.
257
258 /// The type of the condition for the emitting switch statement.
260
261 clang::ASTContext &getContext() const { return cgm.getASTContext(); }
262
263 CIRGenBuilderTy &getBuilder() { return builder; }
264
266 const CIRGenModule &getCIRGenModule() const { return cgm; }
267
269 // We currently assume this isn't called for a global initializer.
270 auto fn = mlir::cast<cir::FuncOp>(curFn);
271 return &fn.getRegion().front();
272 }
273
274 /// Sanitizers enabled for this function.
276
278 public:
282
283 private:
284 void ConstructorHelper(clang::FPOptions FPFeatures);
285 CIRGenFunction &cgf;
286 clang::FPOptions oldFPFeatures;
288 llvm::RoundingMode oldRounding;
289 };
291
292 /// The symbol table maps a variable name to a value in the current scope.
293 /// Entering a function creates a new scope, and the function arguments are
294 /// added to the mapping. When the processing of a function is terminated,
295 /// the scope is destroyed and the mappings created in this scope are
296 /// dropped.
297 using SymTableTy = llvm::ScopedHashTable<const clang::Decl *, mlir::Value>;
299
300 /// Whether a cir.stacksave operation has been added. Used to avoid
301 /// inserting cir.stacksave for multiple VLAs in the same scope.
302 bool didCallStackSave = false;
303
304 /// Whether or not a Microsoft-style asm block has been processed within
305 /// this fuction. These can potentially set the return value.
306 bool sawAsmBlock = false;
307
308 /// In C++, whether we are code generating a thunk. This controls whether we
309 /// should emit cleanups.
310 bool curFuncIsThunk = false;
311
312 mlir::Type convertTypeForMem(QualType t);
313
314 mlir::Type convertType(clang::QualType t);
315 mlir::Type convertType(const TypeDecl *t) {
316 return convertType(getContext().getTypeDeclType(t));
317 }
318
319 /// Get integer from a mlir::Value that is an int constant or a constant op.
320 static int64_t getSExtIntValueFromConstOp(mlir::Value val) {
321 auto constOp = val.getDefiningOp<cir::ConstantOp>();
322 assert(constOp && "getSExtIntValueFromConstOp call with non ConstantOp");
323 return constOp.getIntValue().getSExtValue();
324 }
325
326 /// Get zero-extended integer from a mlir::Value that is an int constant or a
327 /// constant op.
328 static int64_t getZExtIntValueFromConstOp(mlir::Value val) {
329 auto constOp = val.getDefiningOp<cir::ConstantOp>();
330 assert(constOp && "getZExtIntValueFromConstOp call with non ConstantOp");
331 return constOp.getIntValue().getZExtValue();
332 }
333
334 /// Return the cir::TypeEvaluationKind of QualType \c type.
336
340
344
346 bool suppressNewContext = false);
348
349 CIRGenTypes &getTypes() const { return cgm.getTypes(); }
350
351 const TargetInfo &getTarget() const { return cgm.getTarget(); }
352 mlir::MLIRContext &getMLIRContext() { return cgm.getMLIRContext(); }
353
355 return cgm.getTargetCIRGenInfo();
356 }
357
358 // ---------------------
359 // Opaque value handling
360 // ---------------------
361
362 /// Keeps track of the current set of opaque value expressions.
363 llvm::DenseMap<const OpaqueValueExpr *, LValue> opaqueLValues;
364 llvm::DenseMap<const OpaqueValueExpr *, RValue> opaqueRValues;
365
366 // This keeps track of the associated size for each VLA type.
367 // We track this by the size expression rather than the type itself because
368 // in certain situations, like a const qualifier applied to an VLA typedef,
369 // multiple VLA types can share the same size expression.
370 // FIXME: Maybe this could be a stack of maps that is pushed/popped as we
371 // enter/leave scopes.
372 llvm::DenseMap<const Expr *, mlir::Value> vlaSizeMap;
373
374public:
375 /// A non-RAII class containing all the information about a bound
376 /// opaque value. OpaqueValueMapping, below, is a RAII wrapper for
377 /// this which makes individual mappings very simple; using this
378 /// class directly is useful when you have a variable number of
379 /// opaque values or don't want the RAII functionality for some
380 /// reason.
381 class OpaqueValueMappingData {
382 const OpaqueValueExpr *opaqueValue;
383 bool boundLValue;
384
385 OpaqueValueMappingData(const OpaqueValueExpr *ov, bool boundLValue)
386 : opaqueValue(ov), boundLValue(boundLValue) {}
387
388 public:
389 OpaqueValueMappingData() : opaqueValue(nullptr) {}
390
391 static bool shouldBindAsLValue(const Expr *expr) {
392 // gl-values should be bound as l-values for obvious reasons.
393 // Records should be bound as l-values because IR generation
394 // always keeps them in memory. Expressions of function type
395 // act exactly like l-values but are formally required to be
396 // r-values in C.
397 return expr->isGLValue() || expr->getType()->isFunctionType() ||
399 }
400
402 bind(CIRGenFunction &cgf, const OpaqueValueExpr *ov, const Expr *e) {
403 if (shouldBindAsLValue(ov))
404 return bind(cgf, ov, cgf.emitLValue(e));
405 return bind(cgf, ov, cgf.emitAnyExpr(e));
406 }
407
409 bind(CIRGenFunction &cgf, const OpaqueValueExpr *ov, const LValue &lv) {
410 assert(shouldBindAsLValue(ov));
411 cgf.opaqueLValues.insert(std::make_pair(ov, lv));
412 return OpaqueValueMappingData(ov, true);
413 }
414
416 bind(CIRGenFunction &cgf, const OpaqueValueExpr *ov, const RValue &rv) {
417 assert(!shouldBindAsLValue(ov));
418 cgf.opaqueRValues.insert(std::make_pair(ov, rv));
419
420 OpaqueValueMappingData data(ov, false);
421
422 // Work around an extremely aggressive peephole optimization in
423 // EmitScalarConversion which assumes that all other uses of a
424 // value are extant.
426 return data;
427 }
428
429 bool isValid() const { return opaqueValue != nullptr; }
430 void clear() { opaqueValue = nullptr; }
431
433 assert(opaqueValue && "no data to unbind!");
434
435 if (boundLValue) {
436 cgf.opaqueLValues.erase(opaqueValue);
437 } else {
438 cgf.opaqueRValues.erase(opaqueValue);
440 }
441 }
442 };
443
444 /// An RAII object to set (and then clear) a mapping for an OpaqueValueExpr.
446 CIRGenFunction &cgf;
448
449 public:
453
454 /// Build the opaque value mapping for the given conditional
455 /// operator if it's the GNU ?: extension. This is a common
456 /// enough pattern that the convenience operator is really
457 /// helpful.
458 ///
461 : cgf(cgf) {
462 if (mlir::isa<ConditionalOperator>(op))
463 // Leave Data empty.
464 return;
465
467 mlir::cast<BinaryConditionalOperator>(op);
469 e->getCommon());
470 }
471
472 /// Build the opaque value mapping for an OpaqueValueExpr whose source
473 /// expression is set to the expression the OVE represents.
475 : cgf(cgf) {
476 if (ov) {
477 assert(ov->getSourceExpr() && "wrong form of OpaqueValueMapping used "
478 "for OVE with no source expression");
479 data = OpaqueValueMappingData::bind(cgf, ov, ov->getSourceExpr());
480 }
481 }
482
484 LValue lvalue)
485 : cgf(cgf),
486 data(OpaqueValueMappingData::bind(cgf, opaqueValue, lvalue)) {}
487
489 RValue rvalue)
490 : cgf(cgf),
491 data(OpaqueValueMappingData::bind(cgf, opaqueValue, rvalue)) {}
492
493 void pop() {
494 data.unbind(cgf);
495 data.clear();
496 }
497
499 if (data.isValid())
500 data.unbind(cgf);
501 }
502 };
503
504private:
505 /// Declare a variable in the current scope, return success if the variable
506 /// wasn't declared yet.
507 void declare(mlir::Value addrVal, const clang::Decl *var, clang::QualType ty,
508 mlir::Location loc, clang::CharUnits alignment,
509 bool isParam = false);
510
511public:
512 mlir::Value createDummyValue(mlir::Location loc, clang::QualType qt);
513
514 void emitNullInitialization(mlir::Location loc, Address destPtr, QualType ty);
515
516private:
517 // Track current variable initialization (if there's one)
518 const clang::VarDecl *currVarDecl = nullptr;
519 class VarDeclContext {
521 const clang::VarDecl *oldVal = nullptr;
522
523 public:
524 VarDeclContext(CIRGenFunction &p, const VarDecl *value) : p(p) {
525 if (p.currVarDecl)
526 oldVal = p.currVarDecl;
527 p.currVarDecl = value;
528 }
529
530 /// Can be used to restore the state early, before the dtor
531 /// is run.
532 void restore() { p.currVarDecl = oldVal; }
533 ~VarDeclContext() { restore(); }
534 };
535
536public:
537 /// Use to track source locations across nested visitor traversals.
538 /// Always use a `SourceLocRAIIObject` to change currSrcLoc.
539 std::optional<SourceRange> currSrcLoc;
540
542 CIRGenFunction &cgf;
543 std::optional<SourceRange> oldLoc;
544
545 public:
547 if (cgf.currSrcLoc)
548 oldLoc = cgf.currSrcLoc;
549 cgf.currSrcLoc = value;
550 }
551
552 /// Can be used to restore the state early, before the dtor
553 /// is run.
554 void restore() { cgf.currSrcLoc = oldLoc; }
556 };
557
559 llvm::ScopedHashTableScope<const clang::Decl *, mlir::Value>;
560
561 /// Hold counters for incrementally naming temporaries
562 unsigned counterRefTmp = 0;
563 unsigned counterAggTmp = 0;
564 std::string getCounterRefTmpAsString();
565 std::string getCounterAggTmpAsString();
566
567 /// Helpers to convert Clang's SourceLocation to a MLIR Location.
568 mlir::Location getLoc(clang::SourceLocation srcLoc);
569 mlir::Location getLoc(clang::SourceRange srcLoc);
570 mlir::Location getLoc(mlir::Location lhs, mlir::Location rhs);
571
572 const clang::LangOptions &getLangOpts() const { return cgm.getLangOpts(); }
573
574 /// True if an insertion point is defined. If not, this indicates that the
575 /// current code being emitted is unreachable.
576 /// FIXME(cir): we need to inspect this and perhaps use a cleaner mechanism
577 /// since we don't yet force null insertion point to designate behavior (like
578 /// LLVM's codegen does) and we probably shouldn't.
579 bool haveInsertPoint() const {
580 return builder.getInsertionBlock() != nullptr;
581 }
582
583 // Wrapper for function prototype sources. Wraps either a FunctionProtoType or
584 // an ObjCMethodDecl.
586 llvm::PointerUnion<const clang::FunctionProtoType *,
587 const clang::ObjCMethodDecl *>
589
592 };
593
595
598 RValue emitAtomicLoad(LValue lvalue, SourceLocation loc, cir::MemOrder order,
599 bool isVolatile = false,
601
602 /// An abstract representation of regular/ObjC call/message targets.
604 /// The function declaration of the callee.
605 [[maybe_unused]] const clang::Decl *calleeDecl;
606
607 public:
608 AbstractCallee() : calleeDecl(nullptr) {}
609 AbstractCallee(const clang::FunctionDecl *fd) : calleeDecl(fd) {}
610
611 bool hasFunctionDecl() const {
612 return llvm::isa_and_nonnull<clang::FunctionDecl>(calleeDecl);
613 }
614
615 const clang::Decl *getDecl() const { return calleeDecl; }
616
617 unsigned getNumParams() const {
618 if (const auto *fd = llvm::dyn_cast<clang::FunctionDecl>(calleeDecl))
619 return fd->getNumParams();
620 return llvm::cast<clang::ObjCMethodDecl>(calleeDecl)->param_size();
621 }
622
623 const clang::ParmVarDecl *getParamDecl(unsigned I) const {
624 if (const auto *fd = llvm::dyn_cast<clang::FunctionDecl>(calleeDecl))
625 return fd->getParamDecl(I);
626 return *(llvm::cast<clang::ObjCMethodDecl>(calleeDecl)->param_begin() +
627 I);
628 }
629 };
630
631 /// True if the current statement has noinline attribute.
633
634 /// True if the current statement has always_inline attribute.
636
637 // The CallExpr within the current statement that the musttail attribute
638 // applies to. nullptr if there is no 'musttail' on the current statement.
639 const CallExpr *mustTailCall = nullptr;
640
641 struct VlaSizePair {
642 mlir::Value numElts;
644
645 VlaSizePair(mlir::Value num, QualType ty) : numElts(num), type(ty) {}
646 };
647
648 /// Return the number of elements for a single dimension
649 /// for the given array type.
650 VlaSizePair getVLAElements1D(const VariableArrayType *vla);
651
652 /// Returns an MLIR::Value+QualType pair that corresponds to the size,
653 /// in non-variably-sized elements, of a variable length array type,
654 /// plus that largest non-variably-sized element type. Assumes that
655 /// the type has already been emitted with emitVariablyModifiedType.
656 VlaSizePair getVLASize(const VariableArrayType *type);
657 VlaSizePair getVLASize(QualType type);
658
660
661 mlir::Value getAsNaturalPointerTo(Address addr, QualType pointeeType) {
662 return getAsNaturalAddressOf(addr, pointeeType).getBasePointer();
663 }
664
665 void finishFunction(SourceLocation endLoc);
666
667 /// Determine whether the given initializer is trivial in the sense
668 /// that it requires no code to be generated.
669 bool isTrivialInitializer(const Expr *init);
670
671 /// If the specified expression does not fold to a constant, or if it does but
672 /// contains a label, return false. If it constant folds return true and set
673 /// the boolean result in Result.
674 bool constantFoldsToBool(const clang::Expr *cond, bool &resultBool,
675 bool allowLabels = false);
677 llvm::APSInt &resultInt,
678 bool allowLabels = false);
679
680 /// Return true if the statement contains a label in it. If
681 /// this statement is not executed normally, it not containing a label means
682 /// that we can just remove the code.
683 bool containsLabel(const clang::Stmt *s, bool ignoreCaseStmts = false);
684
685 Address emitExtVectorElementLValue(LValue lv, mlir::Location loc);
686
687 class ConstantEmission {
688 // Cannot use mlir::TypedAttr directly here because of bit availability.
689 llvm::PointerIntPair<mlir::Attribute, 1, bool> valueAndIsReference;
690 ConstantEmission(mlir::TypedAttr c, bool isReference)
691 : valueAndIsReference(c, isReference) {}
692
693 public:
695 static ConstantEmission forReference(mlir::TypedAttr c) {
696 return ConstantEmission(c, true);
697 }
698 static ConstantEmission forValue(mlir::TypedAttr c) {
699 return ConstantEmission(c, false);
700 }
701
702 explicit operator bool() const {
703 return valueAndIsReference.getOpaqueValue() != nullptr;
704 }
705
706 bool isReference() const { return valueAndIsReference.getInt(); }
708 assert(isReference());
709 cgf.cgm.errorNYI(refExpr->getSourceRange(),
710 "ConstantEmission::getReferenceLValue");
711 return {};
712 }
713
714 mlir::TypedAttr getValue() const {
715 assert(!isReference());
716 return mlir::cast<mlir::TypedAttr>(valueAndIsReference.getPointer());
717 }
718 };
719
720 ConstantEmission tryEmitAsConstant(const DeclRefExpr *refExpr);
721 ConstantEmission tryEmitAsConstant(const MemberExpr *me);
722
725 /// The address of the alloca for languages with explicit address space
726 /// (e.g. OpenCL) or alloca casted to generic pointer for address space
727 /// agnostic languages (e.g. C++). Invalid if the variable was emitted
728 /// as a global constant.
730
731 /// True if the variable is of aggregate type and has a constant
732 /// initializer.
734
735 /// True if the variable is a __block variable that is captured by an
736 /// escaping block.
737 bool isEscapingByRef = false;
738
739 /// True if the variable was emitted as an offload recipe, and thus doesn't
740 /// have the same sort of alloca initialization.
741 bool emittedAsOffload = false;
742
743 /// True if lifetime op should be used.
744 bool useLifetimeMarkers = false;
745
746 mlir::Value nrvoFlag{};
747
748 struct Invalid {};
750
753
755
756 bool wasEmittedAsGlobal() const { return !addr.isValid(); }
757
759
760 /// Returns the raw, allocated address, which is not necessarily
761 /// the address of the object itself. It is casted to default
762 /// address space for address space agnostic languages.
763 Address getAllocatedAddress() const { return addr; }
764
765 // Changes the stored address for the emission. This function should only
766 // be used in extreme cases, and isn't required to model normal AST
767 // initialization/variables.
769
770 /// Returns the address of the object within this declaration.
771 /// Note that this does not chase the forwarding pointer for
772 /// __block decls.
774 if (!isEscapingByRef)
775 return addr;
776
778 return Address::invalid();
779 }
780 };
781
782 /// Perform the usual unary conversions on the specified expression and
783 /// compare the result against zero, returning an Int1Ty value.
784 mlir::Value evaluateExprAsBool(const clang::Expr *e);
785
786 cir::GlobalOp addInitializerToStaticVarDecl(const VarDecl &d,
787 cir::GlobalOp gv,
788 cir::GetGlobalOp gvAddr);
789
790 /// Enter the cleanups necessary to complete the given phase of destruction
791 /// for a destructor. The end result should call destructors on members and
792 /// base classes in reverse order of their construction.
794
795 /// Determines whether an EH cleanup is required to destroy a type
796 /// with the given destruction kind.
797 /// TODO(cir): could be shared with Clang LLVM codegen
799 switch (kind) {
801 return false;
805 return getLangOpts().Exceptions;
807 return getLangOpts().Exceptions &&
808 cgm.getCodeGenOpts().ObjCAutoRefCountExceptions;
809 }
810 llvm_unreachable("bad destruction kind");
811 }
812
816
818
819 /// Set the address of a local variable.
821 assert(!localDeclMap.count(vd) && "Decl already exists in LocalDeclMap!");
822 localDeclMap.insert({vd, addr});
823
824 // Add to the symbol table if not there already.
825 if (symbolTable.count(vd))
826 return;
827 symbolTable.insert(vd, addr.getPointer());
828 }
829
830 // Replaces the address of the local variable, if it exists. Else does the
831 // same thing as setAddrOfLocalVar.
833 localDeclMap.insert_or_assign(vd, addr);
834 }
835
836 // A class to allow reverting changes to a var-decl's registration to the
837 // localDeclMap. This is used in cases where things are being inserted into
838 // the variable list but don't follow normal lookup/search rules, like in
839 // OpenACC recipe generation.
841 CIRGenFunction &cgf;
842 const VarDecl *vd;
843 bool shouldDelete = false;
844 Address oldAddr = Address::invalid();
845
846 public:
848 : cgf(cgf), vd(vd) {
849 auto mapItr = cgf.localDeclMap.find(vd);
850
851 if (mapItr != cgf.localDeclMap.end())
852 oldAddr = mapItr->second;
853 else
854 shouldDelete = true;
855 }
856
858 if (shouldDelete)
859 cgf.localDeclMap.erase(vd);
860 else
861 cgf.localDeclMap.insert_or_assign(vd, oldAddr);
862 }
863 };
864
866
869
870 static bool
872
879
882
886 const clang::CXXRecordDecl *nearestVBase,
887 clang::CharUnits offsetFromNearestVBase,
888 bool baseIsNonVirtualPrimaryBase,
889 const clang::CXXRecordDecl *vtableClass,
890 VisitedVirtualBasesSetTy &vbases, VPtrsVector &vptrs);
891 /// Return the Value of the vtable pointer member pointed to by thisAddr.
892 mlir::Value getVTablePtr(mlir::Location loc, Address thisAddr,
893 const clang::CXXRecordDecl *vtableClass);
894
895 /// Returns whether we should perform a type checked load when loading a
896 /// virtual function for virtual calls to members of RD. This is generally
897 /// true when both vcall CFI and whole-program-vtables are enabled.
899
900 /// Source location information about the default argument or member
901 /// initializer expression we're evaluating, if any.
905
906 /// A scope within which we are constructing the fields of an object which
907 /// might use a CXXDefaultInitExpr. This stashes away a 'this' value to use if
908 /// we need to evaluate the CXXDefaultInitExpr within the evaluation.
910 public:
912 : cgf(cgf), oldCXXDefaultInitExprThis(cgf.cxxDefaultInitExprThis) {
913 cgf.cxxDefaultInitExprThis = thisAddr;
914 }
916 cgf.cxxDefaultInitExprThis = oldCXXDefaultInitExprThis;
917 }
918
919 private:
920 CIRGenFunction &cgf;
921 Address oldCXXDefaultInitExprThis;
922 };
923
924 /// The scope of a CXXDefaultInitExpr. Within this scope, the value of 'this'
925 /// is overridden to be the object under construction.
927 public:
932 cgf.cxxThisValue = cgf.cxxDefaultInitExprThis.getPointer();
933 cgf.cxxThisAlignment = cgf.cxxDefaultInitExprThis.getAlignment();
934 }
936 cgf.cxxThisValue = oldCXXThisValue;
937 cgf.cxxThisAlignment = oldCXXThisAlignment;
938 }
939
940 public:
942 mlir::Value oldCXXThisValue;
945 };
946
951
952 /// The scope of an ArrayInitLoopExpr. Within this scope, the value of the
953 /// current loop index is overridden. In order to encourage re-use of existing
954 /// array initialization, this uses a flag to determine if it is a 'no-op' or
955 /// not.
957 public:
958 ArrayInitLoopExprScope(CIRGenFunction &cgf, bool setIdx, mlir::Value index)
959 : cgf(cgf),
960 oldArrayInitIndex(setIdx
961 ? std::optional<mlir::Value>(cgf.arrayInitIndex)
962 : std::nullopt) {
963 if (setIdx)
964 cgf.arrayInitIndex = index;
965 }
967 if (oldArrayInitIndex.has_value())
968 cgf.arrayInitIndex = *oldArrayInitIndex;
969 }
970
971 private:
972 CIRGenFunction &cgf;
973 std::optional<mlir::Value> oldArrayInitIndex;
974 };
975
976 /// Get the index of the current ArrayInitLoopExpr, if any.
977 mlir::Value getArrayInitIndex() { return arrayInitIndex; }
978
980 LValue makeNaturalAlignAddrLValue(mlir::Value val, QualType ty);
981
982 /// Construct an address with the natural alignment of T. If a pointer to T
983 /// is expected to be signed, the pointer passed to this function must have
984 /// been signed, and the returned Address will have the pointer authentication
985 /// information needed to authenticate the signed pointer.
987 CharUnits alignment,
988 bool forPointeeType = false,
989 LValueBaseInfo *baseInfo = nullptr) {
990 if (alignment.isZero())
991 alignment = cgm.getNaturalTypeAlignment(t, baseInfo);
992 return Address(ptr, convertTypeForMem(t), alignment);
993 }
994
996 Address value, const CXXRecordDecl *derived,
997 llvm::iterator_range<CastExpr::path_const_iterator> path,
998 bool nullCheckValue, SourceLocation loc);
999
1001 mlir::Location loc, Address baseAddr, const CXXRecordDecl *derived,
1002 llvm::iterator_range<CastExpr::path_const_iterator> path,
1003 bool nullCheckValue);
1004
1005 /// Return the VTT parameter that should be passed to a base
1006 /// constructor/destructor with virtual bases.
1007 /// FIXME: VTTs are Itanium ABI-specific, so the definition should move
1008 /// to ItaniumCXXABI.cpp together with all the references to VTT.
1009 mlir::Value getVTTParameter(GlobalDecl gd, bool forVirtualBase,
1010 bool delegating);
1011
1014 return makeAddrLValue(addr, ty, LValueBaseInfo(source));
1015 }
1016
1018 return LValue::makeAddr(addr, ty, baseInfo);
1019 }
1020
1021 void initializeVTablePointers(mlir::Location loc,
1022 const clang::CXXRecordDecl *rd);
1023 void initializeVTablePointer(mlir::Location loc, const VPtr &vptr);
1024
1026
1027 /// Return the address of a local variable.
1029 auto it = localDeclMap.find(vd);
1030 assert(it != localDeclMap.end() &&
1031 "Invalid argument to getAddrOfLocalVar(), no decl!");
1032 return it->second;
1033 }
1034
1036 mlir::Type fieldType, unsigned index);
1037
1038 /// Given an opaque value expression, return its LValue mapping if it exists,
1039 /// otherwise create one.
1041
1042 /// Given an opaque value expression, return its RValue mapping if it exists,
1043 /// otherwise create one.
1045
1046 /// Load the value for 'this'. This function is only valid while generating
1047 /// code for an C++ member function.
1048 /// FIXME(cir): this should return a mlir::Value!
1049 mlir::Value loadCXXThis() {
1050 assert(cxxThisValue && "no 'this' value for this function");
1051 return cxxThisValue;
1052 }
1054
1055 /// Load the VTT parameter to base constructors/destructors have virtual
1056 /// bases. FIXME: Every place that calls LoadCXXVTT is something that needs to
1057 /// be abstracted properly.
1058 mlir::Value loadCXXVTT() {
1059 assert(cxxStructorImplicitParamValue && "no VTT value for this function");
1061 }
1062
1063 /// Convert the given pointer to a complete class to the given direct base.
1065 Address value,
1066 const CXXRecordDecl *derived,
1067 const CXXRecordDecl *base,
1068 bool baseIsVirtual);
1069
1070 /// Determine whether a return value slot may overlap some other object.
1072 // FIXME: Assuming no overlap here breaks guaranteed copy elision for base
1073 // class subobjects. These cases may need to be revisited depending on the
1074 // resolution of the relevant core issue.
1076 }
1077
1078 /// Determine whether a base class initialization may overlap some other
1079 /// object.
1081 const CXXRecordDecl *baseRD,
1082 bool isVirtual);
1083
1084 /// Return a CIR constant for an undefined value of \p cirTy.
1085 mlir::Value getUndefConstant(mlir::Location loc, mlir::Type cirTy);
1086
1087 /// Get an appropriate 'undef' rvalue for the given type.
1089
1090 cir::FuncOp generateCode(clang::GlobalDecl gd, cir::FuncOp fn,
1091 cir::FuncType funcType);
1092
1094 FunctionArgList &args);
1095
1096 /// Emit the function prologue: declare function arguments in the symbol
1097 /// table.
1098 void emitFunctionProlog(const FunctionArgList &args, mlir::Block *entryBB,
1099 const FunctionDecl *fd, SourceLocation bodyBeginLoc);
1100
1101 /// Emit code for the start of a function.
1102 /// \param loc The location to be associated with the function.
1103 /// \param startLoc The location of the function body.
1105 cir::FuncOp fn, cir::FuncType funcType,
1107 clang::SourceLocation startLoc);
1108
1109 /// returns true if aggregate type has a volatile member.
1111 if (const auto *rd = t->getAsRecordDecl())
1112 return rd->hasVolatileMember();
1113 return false;
1114 }
1115
1116 void addCatchHandlerAttr(const CXXCatchStmt *catchStmt,
1117 SmallVector<mlir::Attribute> &handlerAttrs);
1118
1119 /// The cleanup depth enclosing all the cleanups associated with the
1120 /// parameters.
1122
1124
1125 /// Takes the old cleanup stack size and emits the cleanup blocks
1126 /// that have been added.
1127 void popCleanupBlocks(EHScopeStack::stable_iterator oldCleanupStackDepth,
1128 ArrayRef<mlir::Value *> valuesToReload = {});
1129
1130 /// Pops cleanup blocks until the given savepoint is reached, then adds the
1131 /// cleanups from the given savepoint in the lifetime-extended cleanups stack.
1132 void popCleanupBlocks(EHScopeStack::stable_iterator oldCleanupStackDepth,
1133 size_t oldLifetimeExtendedSize,
1134 ArrayRef<mlir::Value *> valuesToReload = {});
1135 void popCleanupBlock(bool forDeactivation = false);
1136
1137 /// Emit the cleanups captured for a loop's condition variable (those pushed
1138 /// above \p depth while EHScopeStack was capturing condition cleanups) at
1139 /// the current insertion point, which must be inside the loop op's cleanup
1140 /// region, and pop them off the EH stack.
1141 void emitLoopConditionCleanups(EHScopeStack::stable_iterator depth,
1142 mlir::Location loc);
1143
1144 void terminateStructuredRegionBody(mlir::Region &r, mlir::Location loc);
1145
1146 /// Deactivates the given cleanup block. The block cannot be reactivated. Pops
1147 /// it if it's the top of the stack.
1148 ///
1149 /// \param DominatingIP - An instruction which is known to
1150 /// dominate the current IP (if set) and which lies along
1151 /// all paths of execution between the current IP and the
1152 /// the point at which the cleanup comes into scope.
1153 void deactivateCleanupBlock(EHScopeStack::stable_iterator cleanup,
1154 mlir::Operation *dominatingIP);
1155
1156 /// Create an active flag variable for use with conditional cleanups. The
1157 /// flag is initialized to false before the outermost conditional and set to
1158 /// true at the current insertion point (inside the conditional branch).
1159 Address createCleanupActiveFlag();
1160
1161 /// Set up the last cleanup that was pushed as a conditional
1162 /// full-expression cleanup.
1163 void initFullExprCleanup();
1164 void initFullExprCleanupWithFlag(Address activeFlag);
1165
1166 /// Promote a single pending cleanup entry onto the EH scope stack. If the
1167 /// entry has a valid activeFlag, the cleanup is configured as conditional.
1168 /// Defined in CIRGenDecl.cpp where the concrete cleanup types are visible.
1169 void pushPendingCleanupToEHStack(const PendingCleanupEntry &entry);
1170
1171 /// Push a cleanup to be run at the end of the current full-expression. Safe
1172 /// against the possibility that we're currently inside a
1173 /// conditionally-evaluated expression.
1174 template <class T, class... As>
1176 if (!isInConditionalBranch())
1177 return ehStack.pushCleanup<T>(kind, a...);
1178
1179 // Defer the cleanup until the FullExprCleanupScope exits. We can't push
1180 // to the EH stack now because the ternary's inner LexicalScope would pop
1181 // it prematurely.
1182 Address activeFlag = createCleanupActiveFlag();
1184 PendingCleanupEntry{kind, a..., activeFlag});
1185 }
1186
1187 /// Push a cleanup and record it for deferred deactivation. The cleanup will
1188 /// be deactivated when the enclosing CleanupDeactivationScope exits.
1189 template <class T, class... As>
1191 mlir::Location loc = builder.getUnknownLoc();
1192 mlir::Operation *dominatingIP = builder.getBool(false, loc).getOperation();
1193 ehStack.pushCleanup<T>(kind, a...);
1195 {ehStack.stable_begin(), dominatingIP});
1196 }
1197
1199 Address addr, QualType type);
1201 QualType type, Destroyer *destroyer,
1202 bool useEHCleanupForArray);
1203
1204 /// Queue a cleanup to be pushed after finishing the current full-expression.
1205 /// When the enclosing RunCleanupsScope exits, popCleanupBlocks promotes these
1206 /// entries onto the EH scope stack for the enclosing scope.
1208 Destroyer *destroyer) {
1209 lifetimeExtendedCleanupStack.push_back({kind, addr, type, destroyer});
1210 }
1211
1212 /// Enters a new scope for capturing cleanups, all of which
1213 /// will be executed once the scope is exited.
1214 class RunCleanupsScope {
1215 EHScopeStack::stable_iterator cleanupStackDepth, oldCleanupStackDepth;
1216 size_t lifetimeExtendedCleanupStackSize;
1217 CleanupDeactivationScope deactivateCleanups;
1218
1219 protected:
1222
1223 private:
1224 RunCleanupsScope(const RunCleanupsScope &) = delete;
1225 void operator=(const RunCleanupsScope &) = delete;
1226
1227 protected:
1229
1230 public:
1231 /// Enter a new cleanup scope.
1233 : deactivateCleanups(cgf), performCleanup(true), cgf(cgf) {
1234 cleanupStackDepth = cgf.ehStack.stable_begin();
1235 lifetimeExtendedCleanupStackSize =
1236 cgf.lifetimeExtendedCleanupStack.size();
1237 oldDidCallStackSave = cgf.didCallStackSave;
1238 cgf.didCallStackSave = false;
1239 oldCleanupStackDepth = cgf.currentCleanupStackDepth;
1240 cgf.currentCleanupStackDepth = cleanupStackDepth;
1241 }
1242
1243 /// Exit this cleanup scope, emitting any accumulated cleanups.
1245 if (performCleanup)
1246 forceCleanup();
1247 }
1248
1249 /// Force the emission of cleanups now, instead of waiting
1250 /// until this object is destroyed.
1251 void forceCleanup(ArrayRef<mlir::Value *> valuesToReload = {}) {
1252 assert(performCleanup && "Already forced cleanup");
1254
1255 // forceDeactivate() can pop cleanup scopes that were pushed with
1256 // deferred deactivation, which moves the insertion point out of the
1257 // cleanup body region. Any caller value defined inside such a body
1258 // would no longer dominate uses past the scope. The downstream
1259 // popCleanupBlocks() handles the spill for any cleanups it pops
1260 // itself, but it cannot help with cleanups that forceDeactivate has
1261 // already popped. Spill those values here, while the insertion point
1262 // is still inside the body, so we can reload them after all popping
1263 // is done. We only spill values whose defining op lives inside a
1264 // cir.cleanup.scope, since values defined outside any cleanup scope
1265 // (e.g. allocas in the entry block) already dominate the post-scope
1266 // insertion point.
1267 const bool hasPendingDeactivations =
1269 deactivateCleanups.oldDeactivateCleanupStackSize;
1270
1271 llvm::SmallVector<Address> tempAllocas;
1272 bool didSpillAny = false;
1273 if (hasPendingDeactivations) {
1274 tempAllocas.reserve(valuesToReload.size());
1275 for (mlir::Value *valPtr : valuesToReload) {
1276 mlir::Value val = *valPtr;
1277 if (!val || !val.getDefiningOp() ||
1278 !val.getDefiningOp()->getParentOfType<cir::CleanupScopeOp>()) {
1279 tempAllocas.push_back(Address::invalid());
1280 continue;
1281 }
1283 val.getType(), val.getLoc(), "tmp.exprcleanup");
1284 tempAllocas.push_back(temp);
1285 cgf.builder.createStore(val.getLoc(), val, temp);
1286 didSpillAny = true;
1287 }
1288 }
1289
1290 deactivateCleanups.forceDeactivate();
1291 // If we already spilled some of the caller's values, don't ask
1292 // popCleanupBlocks to spill them again. Values we did not pre-spill
1293 // are not inside any cir.cleanup.scope, so they cannot be invalidated
1294 // by either forceDeactivate's or popCleanupBlocks's pops (both only
1295 // pop cir.cleanup.scope ops); they already dominate the post-scope
1296 // insertion point on their own.
1297 if (didSpillAny) {
1298 cgf.popCleanupBlocks(cleanupStackDepth,
1299 lifetimeExtendedCleanupStackSize);
1300
1301 // Reload the spilled values now that all cleanup popping (and
1302 // promotion of any lifetime-extended cleanups onto the EH stack) is
1303 // done.
1304 for (auto [addr, valPtr] : llvm::zip(tempAllocas, valuesToReload)) {
1305 if (!addr.isValid())
1306 continue;
1307 *valPtr = cgf.builder.createLoad(valPtr->getLoc(), addr);
1308 }
1309 } else {
1310 cgf.popCleanupBlocks(cleanupStackDepth,
1311 lifetimeExtendedCleanupStackSize, valuesToReload);
1312 }
1313
1314 performCleanup = false;
1315 cgf.currentCleanupStackDepth = oldCleanupStackDepth;
1316 }
1317
1318 /// Force the emission of EH cleanups now, but defer promoting any
1319 /// lifetime-extended cleanup entries onto the EH scope stack. The caller
1320 /// must subsequently call forceLifetimeExtendedCleanups() to finalize the
1321 /// scope.
1323 assert(performCleanup && "Already forced cleanup");
1324 cgf.didCallStackSave = oldDidCallStackSave;
1325 deactivateCleanups.forceDeactivate();
1326 cgf.popCleanupBlocks(cleanupStackDepth);
1327 }
1328
1329 /// Promote any pending lifetime-extended cleanup entries onto the EH scope
1330 /// stack at the current insertion point and finalize this scope. This must
1331 /// be paired with a prior call to forceCleanupExceptLifetimeExtended().
1333 assert(performCleanup && "Already forced cleanup");
1334 assert(deactivateCleanups.deactivated &&
1335 "forceCleanupExceptLifetimeExtended() must be called first");
1336 cgf.popCleanupBlocks(cleanupStackDepth, lifetimeExtendedCleanupStackSize);
1337 performCleanup = false;
1338 cgf.currentCleanupStackDepth = oldCleanupStackDepth;
1339 }
1340
1341 /// Whether there are any pending cleanups that have been pushed since
1342 /// this scope was entered.
1343 bool hasPendingCleanups() const {
1344 return cgf.ehStack.stable_begin() != cleanupStackDepth;
1345 }
1346 };
1347
1348 // Cleanup stack depth of the RunCleanupsScope that was pushed most recently.
1350
1352 CIRGenFunction &cgf;
1353 RunCleanupsScope cleanups;
1354 cir::CleanupScopeOp scope;
1355 size_t deferredCleanupStackSize;
1356 bool exited = false;
1357
1358 public:
1359 FullExprCleanupScope(CIRGenFunction &cgf, const Expr *subExpr);
1360
1361 void exit(ArrayRef<mlir::Value *> valuesToReload = {});
1362
1364 if (!exited)
1365 exit();
1366 }
1367
1368 private:
1370 void operator=(const FullExprCleanupScope &) = delete;
1371 };
1372
1373 /// Captures cleanups for a loop's condition variable so that they can be
1374 /// emitted into the loop op's per-iteration cleanup region.
1376 CIRGenFunction &cgf;
1378 bool active;
1379
1380 public:
1382 : cgf(cgf), depth(cgf.ehStack.stable_begin()), active(active) {}
1383
1384 /// An RAII class that suppresses cir.cleanup.scope creation for cleanups
1385 /// pushed onto the EH stack while a loop condition variable is being
1386 /// emitted and instead captures these cleanups so that they can be emitted
1387 /// into the loop op's cleanup region after the condition region is built.
1389 EHScopeStack &ehStack;
1390
1391 public:
1393 : ehStack(scope.cgf.ehStack) {
1394 // Capture scopes deliberately wrap individual cleanup-producing
1395 // operations, so they must never nest.
1396 assert(!ehStack.isCapturingLoopConditionCleanups() &&
1397 "loop condition cleanup capturing should not nest");
1398 if (scope.active)
1399 ehStack.setCapturingLoopConditionCleanups(true);
1400 }
1401 ~CaptureScope() { ehStack.setCapturingLoopConditionCleanups(false); }
1402
1403 CaptureScope(const CaptureScope &) = delete;
1404 void operator=(const CaptureScope &) = delete;
1405 };
1406
1407 /// Emit the captured condition-variable cleanups into the current insertion
1408 /// point (the loop's cleanup region).
1409 void emitIntoLoopCleanupRegion(mlir::Location loc) {
1410 if (active)
1411 cgf.emitLoopConditionCleanups(depth, loc);
1412 }
1413
1414 private:
1416 void operator=(const DeferredLoopConditionCleanup &) = delete;
1417 };
1418
1419public:
1420 /// Represents a scope, including function bodies, compound statements, and
1421 /// the substatements of if/while/do/for/switch/try statements. This class
1422 /// handles any automatic cleanup, along with the return value.
1423 struct LexicalScope : public RunCleanupsScope {
1424 private:
1425 // Points to the scope entry block. This is useful, for instance, for
1426 // helping to insert allocas before finalizing any recursive CodeGen from
1427 // switches.
1428 mlir::Block *entryBlock;
1429
1430 LexicalScope *parentScope = nullptr;
1431
1432 // Holds the actual value for ScopeKind::Try
1433 cir::TryOp tryOp = nullptr;
1434
1435 // On a coroutine body, the OnFallthrough sub stmt holds the handler
1436 // (CoreturnStmt) for control flow falling off the body. Keep track
1437 // of emitted co_return in this scope and allow OnFallthrough to be
1438 // skipeed.
1439 bool hasCoreturnStmt = false;
1440
1441 // Only Regular is used at the moment. Support for other kinds will be
1442 // added as the relevant statements/expressions are upstreamed.
1443 enum Kind {
1444 Regular, // cir.if, cir.scope, if_regions
1445 Ternary, // cir.ternary
1446 Switch, // cir.switch
1447 Try, // cir.try
1448 GlobalInit // cir.global initialization code
1449 };
1450 Kind scopeKind = Kind::Regular;
1451
1452 // The scope return value.
1453 mlir::Value retVal = nullptr;
1454
1455 mlir::Location beginLoc;
1456 mlir::Location endLoc;
1457
1458 public:
1459 unsigned depth = 0;
1460
1461 LexicalScope(CIRGenFunction &cgf, mlir::Location loc, mlir::Block *eb)
1462 : RunCleanupsScope(cgf), entryBlock(eb), parentScope(cgf.curLexScope),
1463 beginLoc(loc), endLoc(loc) {
1464
1465 assert(entryBlock && "LexicalScope requires an entry block");
1466 cgf.curLexScope = this;
1467 if (parentScope)
1468 ++depth;
1469
1470 if (const auto fusedLoc = mlir::dyn_cast<mlir::FusedLoc>(loc)) {
1471 assert(fusedLoc.getLocations().size() == 2 && "too many locations");
1472 beginLoc = fusedLoc.getLocations()[0];
1473 endLoc = fusedLoc.getLocations()[1];
1474 }
1475 }
1476
1477 void setRetVal(mlir::Value v) { retVal = v; }
1478
1479 void cleanup();
1480 void restore() { cgf.curLexScope = parentScope; }
1481
1484 cleanup();
1485 restore();
1486 }
1487
1488 // ---
1489 // Coroutine tracking
1490 // ---
1491 bool hasCoreturn() const { return hasCoreturnStmt; }
1492 void setCoreturn() { hasCoreturnStmt = true; }
1493
1494 // ---
1495 // Kind
1496 // ---
1497 bool isGlobalInit() { return scopeKind == Kind::GlobalInit; }
1498 bool isRegular() { return scopeKind == Kind::Regular; }
1499 bool isSwitch() { return scopeKind == Kind::Switch; }
1500 bool isTernary() { return scopeKind == Kind::Ternary; }
1501 bool isTry() { return scopeKind == Kind::Try; }
1502 cir::TryOp getClosestTryParent();
1503 void setAsGlobalInit() { scopeKind = Kind::GlobalInit; }
1504 void setAsSwitch() { scopeKind = Kind::Switch; }
1505 void setAsTernary() { scopeKind = Kind::Ternary; }
1506 void setAsTry(cir::TryOp op) {
1507 scopeKind = Kind::Try;
1508 tryOp = op;
1509 }
1510
1511 cir::TryOp getTry() {
1512 assert(isTry());
1513 return tryOp;
1514 }
1515
1516 // ---
1517 // Return handling.
1518 // ---
1519
1520 private:
1521 // On switches we need one return block per region, since cases don't
1522 // have their own scopes but are distinct regions nonetheless.
1523
1524 // TODO: This implementation should change once we have support for early
1525 // exits in MLIR structured control flow (llvm-project#161575)
1527 llvm::DenseMap<mlir::Block *, mlir::Location> retLocs;
1528 llvm::DenseMap<cir::CaseOp, unsigned> retBlockInCaseIndex;
1529 std::optional<unsigned> normalRetBlockIndex;
1530
1531 // There's usually only one ret block per scope, but this needs to be
1532 // get or create because of potential unreachable return statements, note
1533 // that for those, all source location maps to the first one found.
1534 mlir::Block *createRetBlock(CIRGenFunction &cgf, mlir::Location loc) {
1535 assert((isa_and_nonnull<cir::CaseOp>(
1536 cgf.builder.getBlock()->getParentOp()) ||
1537 retBlocks.size() == 0) &&
1538 "only switches can hold more than one ret block");
1539
1540 // Create the return block but don't hook it up just yet.
1541 mlir::OpBuilder::InsertionGuard guard(cgf.builder);
1542 auto *b = cgf.builder.createBlock(cgf.builder.getBlock()->getParent());
1543 retBlocks.push_back(b);
1544 updateRetLoc(b, loc);
1545 return b;
1546 }
1547
1548 cir::ReturnOp emitReturn(mlir::Location loc);
1549 void emitImplicitReturn();
1550
1551 public:
1553 mlir::Location getRetLoc(mlir::Block *b) { return retLocs.at(b); }
1554 void updateRetLoc(mlir::Block *b, mlir::Location loc) {
1555 retLocs.insert_or_assign(b, loc);
1556 }
1557
1558 mlir::Block *getOrCreateRetBlock(CIRGenFunction &cgf, mlir::Location loc) {
1559 // Check if we're inside a case region
1560 if (auto caseOp = mlir::dyn_cast_if_present<cir::CaseOp>(
1561 cgf.builder.getBlock()->getParentOp())) {
1562 auto iter = retBlockInCaseIndex.find(caseOp);
1563 if (iter != retBlockInCaseIndex.end()) {
1564 // Reuse existing return block
1565 mlir::Block *ret = retBlocks[iter->second];
1566 updateRetLoc(ret, loc);
1567 return ret;
1568 }
1569 // Create new return block
1570 mlir::Block *ret = createRetBlock(cgf, loc);
1571 retBlockInCaseIndex[caseOp] = retBlocks.size() - 1;
1572 return ret;
1573 }
1574
1575 if (normalRetBlockIndex) {
1576 mlir::Block *ret = retBlocks[*normalRetBlockIndex];
1577 updateRetLoc(ret, loc);
1578 return ret;
1579 }
1580
1581 mlir::Block *ret = createRetBlock(cgf, loc);
1582 normalRetBlockIndex = retBlocks.size() - 1;
1583 return ret;
1584 }
1585
1586 mlir::Block *getEntryBlock() { return entryBlock; }
1587 };
1588
1590
1592
1594 QualType type);
1595
1596 void pushDestroy(QualType::DestructionKind dtorKind, Address addr,
1597 QualType type);
1598
1600 Destroyer *destroyer);
1601
1603 QualType type, Destroyer *destroyer,
1604 bool useEHCleanupForArray);
1605
1607
1608 void pushIrregularPartialArrayCleanup(mlir::Value arrayBegin,
1609 Address arrayEndPointer,
1610 QualType elementType,
1611 CharUnits elementAlign,
1612 Destroyer *destroyer);
1613
1614 /// Start generating a thunk function.
1615 void startThunk(cir::FuncOp fn, GlobalDecl gd,
1616 const CIRGenFunctionInfo &fnInfo, bool isUnprototyped);
1617
1618 /// Finish generating a thunk function.
1619 void finishThunk();
1620
1621 /// Generate code for a thunk function.
1622 void generateThunk(cir::FuncOp fn, SourceRange fnLoc,
1623 const CIRGenFunctionInfo &fnInfo, GlobalDecl gd,
1624 const ThunkInfo &thunk, bool isUnprototyped);
1625
1626 /// ----------------------
1627 /// CIR emit functions
1628 /// ----------------------
1629public:
1630 bool getAArch64SVEProcessedOperands(unsigned builtinID, const CallExpr *expr,
1632 clang::SVETypeFlags typeFlags);
1633 mlir::Value emitSVEPredicateCast(mlir::Value pred, unsigned minNumElts,
1634 mlir::Location loc);
1635 std::optional<mlir::Value>
1636 emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr,
1638 llvm::Triple::ArchType arch);
1639 std::optional<mlir::Value> emitAArch64SMEBuiltinExpr(unsigned builtinID,
1640 const CallExpr *expr);
1641 std::optional<mlir::Value> emitAArch64SVEBuiltinExpr(unsigned builtinID,
1642 const CallExpr *expr);
1643
1644 mlir::Value emitAlignmentAssumption(mlir::Value ptrValue, QualType ty,
1645 SourceLocation loc,
1646 SourceLocation assumptionLoc,
1647 int64_t alignment,
1648 mlir::Value offsetValue = nullptr);
1649
1650 mlir::Value emitAlignmentAssumption(mlir::Value ptrValue, const Expr *expr,
1651 SourceLocation assumptionLoc,
1652 int64_t alignment,
1653 mlir::Value offsetValue = nullptr);
1654
1655 bool emitLifetimeStartOp(mlir::Location loc, mlir::Value addr);
1656 void emitLifetimeEndOp(mlir::Location loc, mlir::Value addr);
1657
1658private:
1659 void emitAndUpdateRetAlloca(clang::QualType type, mlir::Location loc,
1660 clang::CharUnits alignment);
1661
1662 CIRGenCallee emitDirectCallee(const GlobalDecl &gd);
1663
1664public:
1666 llvm::StringRef fieldName,
1667 unsigned fieldIndex);
1668
1669 mlir::Value emitAlloca(llvm::StringRef name, mlir::Type ty,
1670 mlir::Location loc, clang::CharUnits alignment,
1671 bool insertIntoFnEntryBlock,
1672 mlir::Value arraySize = nullptr);
1673 mlir::Value emitAlloca(llvm::StringRef name, mlir::Type ty,
1674 mlir::Location loc, clang::CharUnits alignment,
1675 mlir::OpBuilder::InsertPoint ip,
1676 mlir::Value arraySize = nullptr);
1677
1678 void emitAggregateStore(mlir::Value value, Address dest);
1679
1680 void emitAggExpr(const clang::Expr *e, AggValueSlot slot);
1681
1683
1685
1686 /// Emit an aggregate copy.
1687 ///
1688 /// \param isVolatile \c true iff either the source or the destination is
1689 /// volatile.
1690 /// \param MayOverlap Whether the tail padding of the destination might be
1691 /// occupied by some other object. More efficient code can often be
1692 /// generated if not.
1693 void emitAggregateCopy(LValue dest, LValue src, QualType eltTy,
1694 AggValueSlot::Overlap_t mayOverlap,
1695 bool isVolatile = false);
1696
1697 /// Emit code to compute the specified expression which can have any type. The
1698 /// result is returned as an RValue struct. If this is an aggregate
1699 /// expression, the aggloc/agglocvolatile arguments indicate where the result
1700 /// should be returned.
1703 bool ignoreResult = false);
1704
1705 /// Emits the code necessary to evaluate an arbitrary expression into the
1706 /// given memory location.
1707 void emitAnyExprToMem(const Expr *e, Address location, Qualifiers quals,
1708 bool isInitializer);
1709
1710 /// Similarly to emitAnyExpr(), however, the result will always be accessible
1711 /// even if no aggregate location is provided.
1713
1714 void emitAnyExprToExn(const Expr *e, Address addr);
1715
1716 void emitArrayDestroy(mlir::Value begin, mlir::Value numElements,
1717 QualType elementType, CharUnits elementAlign,
1718 Destroyer *destroyer);
1719
1720 mlir::Value emitArrayLength(const clang::ArrayType *arrayType,
1721 QualType &baseType, Address &addr);
1724
1726
1728 LValueBaseInfo *baseInfo = nullptr);
1729
1730 std::pair<mlir::Value, mlir::Type>
1732 QualType inputType, std::string &constraintString,
1733 SourceLocation loc);
1734 std::pair<mlir::Value, mlir::Type>
1735 emitAsmInput(const TargetInfo::ConstraintInfo &info, const Expr *inputExpr,
1736 std::string &constraintString);
1737 mlir::LogicalResult emitAsmStmt(const clang::AsmStmt &s);
1738
1740 void emitAtomicInit(Expr *init, LValue dest);
1741 void emitAtomicStore(RValue rvalue, LValue dest, bool isInit);
1742 void emitAtomicStore(RValue rvalue, LValue dest, cir::MemOrder order,
1743 bool isVolatile, bool isInit);
1745 const Expr *memOrder, bool isStore, bool isLoad, bool isFence,
1746 llvm::function_ref<void(cir::MemOrder)> emitAtomicOp);
1747
1748 mlir::Value makeBinaryAtomicValue(
1749 cir::AtomicFetchKind kind, const clang::CallExpr *expr,
1750 mlir::Type *originalArgType = nullptr,
1751 mlir::Value *emittedArgValue = nullptr,
1752 cir::MemOrder ordering = cir::MemOrder::SequentiallyConsistent);
1753
1754 /// Emit `cir.atomic.cmpxchg`. Returns the old value, or the success flag
1755 /// when `returnBool` is true.
1756 mlir::Value emitAtomicCmpXchg(
1757 const clang::CallExpr *expr, bool returnBool,
1758 cir::MemOrder successOrder = cir::MemOrder::SequentiallyConsistent,
1759 cir::MemOrder failureOrder = cir::MemOrder::SequentiallyConsistent,
1760 cir::SyncScopeKind scope = cir::SyncScopeKind::System);
1761
1762 mlir::LogicalResult emitAttributedStmt(const AttributedStmt &s);
1763
1764 AutoVarEmission emitAutoVarAlloca(const clang::VarDecl &d,
1765 mlir::OpBuilder::InsertPoint ip = {});
1766
1768 AggValueSlot slot = AggValueSlot::ignored());
1770
1771 /// Emit code and set up symbol table for a variable declaration with auto,
1772 /// register, or no storage class specifier. These turn into simple stack
1773 /// objects, globals depending on target.
1774 void emitAutoVarDecl(const clang::VarDecl &d);
1775
1776 void emitAutoVarCleanups(const AutoVarEmission &emission);
1777
1778 /// Emit a loop's condition-variable declaration. This needs special handling
1779 /// so that we can manage per-iteration cleanups for the loop condition.
1781 DeferredLoopConditionCleanup &condCleanup);
1782
1783 /// Emit the initializer for an allocated variable. If this call is not
1784 /// associated with the call to emitAutoVarAlloca (as the address of the
1785 /// emission is not directly an alloca), the allocatedSeparately parameter can
1786 /// be used to suppress the assertions. However, this should only be used in
1787 /// extreme cases, as it doesn't properly reflect the language/AST.
1788 void emitAutoVarInit(const AutoVarEmission &emission);
1789 void emitAutoVarTypeCleanup(const AutoVarEmission &emission,
1791
1792 void maybeEmitDeferredVarDeclInit(const VarDecl *vd);
1793
1794 void emitBaseInitializer(mlir::Location loc, const CXXRecordDecl *classDecl,
1795 CXXCtorInitializer *baseInit);
1796
1798
1799 mlir::LogicalResult emitBreakStmt(const clang::BreakStmt &s);
1800
1801 RValue emitBuiltinExpr(const clang::GlobalDecl &gd, unsigned builtinID,
1802 const clang::CallExpr *e, ReturnValueSlot returnValue);
1803
1804 /// Returns a Value corresponding to the size of the given expression by
1805 /// emitting a `cir.objsize` operation.
1806 ///
1807 /// \param e The expression whose object size to compute
1808 /// \param type Determines the semantics of the object size computation.
1809 /// The type parameter is a 2-bit value where:
1810 /// bit 0 (type & 1): 0 = whole object, 1 = closest subobject
1811 /// bit 1 (type & 2): 0 = maximum size, 2 = minimum size
1812 /// \param resType The result type for the size value
1813 /// \param emittedE Optional pre-emitted pointer value. If non-null, we'll
1814 /// call `cir.objsize` on this value rather than emitting e.
1815 /// \param isDynamic If true, allows runtime evaluation via dynamic mode
1816 mlir::Value emitBuiltinObjectSize(const clang::Expr *e, unsigned type,
1817 cir::IntType resType, mlir::Value emittedE,
1818 bool isDynamic);
1819
1820 mlir::Value evaluateOrEmitBuiltinObjectSize(const clang::Expr *e,
1821 unsigned type,
1822 cir::IntType resType,
1823 mlir::Value emittedE,
1824 bool isDynamic);
1825
1826 int64_t getAccessedFieldNo(unsigned idx, mlir::ArrayAttr elts);
1827
1828 /// Emit a simple LLVM intrinsic that takes N scalar arguments. The intrinsic
1829 /// name is used verbatim; any overload mangling (e.g. `.f32`, `.p1`) must be
1830 /// baked into \p intrinName by the caller. The result type defaults to the
1831 /// type of the first argument; pass \p resultType for intrinsics whose result
1832 /// differs from the operand, such as a vector reduction that returns the
1833 /// element type. Unlike classic CodeGen, CIR has no intrinsic registry to
1834 /// derive the result type from the operand, so it must be supplied here.
1835 template <unsigned N>
1836 [[maybe_unused]] RValue
1838 llvm::StringRef intrinName,
1839 mlir::Type resultType = {}) {
1840 static_assert(N, "expect non-empty argument");
1841 mlir::Type cirTy =
1842 resultType ? resultType : convertType(e->getArg(0)->getType());
1844 for (unsigned i = 0; i < N; ++i)
1845 args.push_back(emitScalarExpr(e->getArg(i)));
1846 const auto call = cir::LLVMIntrinsicCallOp::create(
1847 builder, getLoc(e->getExprLoc()), builder.getStringAttr(intrinName),
1848 cirTy, args);
1849 return RValue::get(call->getResult(0));
1850 }
1851
1852 RValue emitCall(const CIRGenFunctionInfo &funcInfo,
1853 const CIRGenCallee &callee, ReturnValueSlot returnValue,
1854 const CallArgList &args, cir::CIRCallOpInterface *callOp,
1855 bool isMustTail, SourceRange clangLoc);
1858 const CallArgList &args, bool isMustTail,
1859 cir::CIRCallOpInterface *callOrTryCall = nullptr) {
1860 assert(currSrcLoc && "source location must have been set");
1861 return emitCall(funcInfo, callee, returnValue, args, callOrTryCall,
1862 isMustTail, *currSrcLoc);
1863 }
1864
1865 RValue emitCall(clang::QualType calleeTy, const CIRGenCallee &callee,
1867
1868 /// Emit the call and return for a thunk function.
1869 void emitCallAndReturnForThunk(cir::FuncOp callee, SourceRange fnLoc,
1870 const ThunkInfo *thunk, bool isUnprototyped);
1871
1872 void emitCallArg(CallArgList &args, const clang::Expr *e,
1873 clang::QualType argType);
1874 void emitCallArgs(
1875 CallArgList &args, PrototypeWrapper prototype,
1876 llvm::iterator_range<clang::CallExpr::const_arg_iterator> argRange,
1877 AbstractCallee callee = AbstractCallee(), unsigned paramsToSkip = 0);
1881
1885
1886 template <typename T>
1887 mlir::LogicalResult emitCaseDefaultCascade(const T *stmt, mlir::Type condType,
1888 mlir::ArrayAttr value,
1889 cir::CaseOpKind kind,
1890 bool buildingTopLevelCase);
1891
1893
1894 mlir::LogicalResult emitCaseStmt(const clang::CaseStmt &s,
1895 mlir::Type condType,
1896 bool buildingTopLevelCase);
1897
1898 LValue emitCastLValue(const CastExpr *e);
1899
1900 /// Emits an argument for a call to a `__builtin_assume`. If the builtin
1901 /// sanitizer is enabled, a runtime check is also emitted.
1902 mlir::Value emitCheckedArgForAssume(const Expr *e);
1903
1904 /// Emit a conversion from the specified complex type to the specified
1905 /// destination type, where the destination type is an LLVM scalar type.
1906 mlir::Value emitComplexToScalarConversion(mlir::Value src, QualType srcTy,
1907 QualType dstTy, SourceLocation loc);
1908
1911
1913
1914 mlir::LogicalResult emitCoroutineBody(const CoroutineBodyStmt &s);
1915 cir::CoroEndOp emitCoroEndBuiltinCall(const CallExpr *e);
1916 cir::CoroIdOp emitCoroIDBuiltinCall(const CallExpr *e);
1917 cir::CoroAllocOp emitCoroAllocBuiltinCall(const CallExpr *e);
1918 cir::CoroBeginOp emitCoroBeginBuiltinCall(const CallExpr *e);
1919 cir::CoroPromiseOp emitCoroPromiseBuiltinCall(const CallExpr *e);
1920 cir::CoroDoneOp emitCoroDoneBuiltinCall(const CallExpr *e);
1921 cir::CoroResumeOp emitCoroResumeBuiltinCall(const CallExpr *e);
1922 cir::CoroDestroyOp emitCoroDestroyBuiltinCall(const CallExpr *e);
1923
1924 cir::CoroSizeOp emitCoroSizeBuiltinCall(const CallExpr *e);
1925 cir::CoroFreeOp emitCoroFreeBuiltin(const CallExpr *e);
1927
1928 void emitDestroy(Address addr, QualType type, Destroyer *destroyer);
1929
1931
1932 mlir::LogicalResult emitContinueStmt(const clang::ContinueStmt &s);
1933
1934 mlir::LogicalResult emitCoreturnStmt(const CoreturnStmt &s);
1935
1937 AggValueSlot dest);
1938
1941 Address arrayBegin, const CXXConstructExpr *e,
1942 bool newPointerIsChecked,
1943 bool zeroInitialize = false);
1945 mlir::Value numElements, Address arrayBase,
1946 const CXXConstructExpr *e,
1947 bool newPointerIsChecked, bool zeroInitialize,
1948 Address endOfInit);
1950 clang::CXXCtorType type, bool forVirtualBase,
1951 bool delegating, AggValueSlot thisAVS,
1952 const clang::CXXConstructExpr *e);
1953
1955 clang::CXXCtorType type, bool forVirtualBase,
1956 bool delegating, Address thisAddr,
1958
1960 bool forVirtualBase, Address thisAddr,
1961 bool inheritedFromVBase,
1962 const CXXInheritedCtorInitExpr *e);
1963
1965 SourceLocation loc, const CXXConstructorDecl *d, CXXCtorType ctorType,
1966 bool forVirtualBase, bool delegating, CallArgList &args);
1967
1968 void emitCXXDeleteExpr(const CXXDeleteExpr *e);
1969
1971 bool forVirtualBase, bool delegating,
1972 Address thisAddr, QualType thisTy);
1973
1975 mlir::Value thisVal, QualType thisTy,
1976 mlir::Value implicitParam,
1977 QualType implicitParamTy, const CallExpr *e);
1978
1979 mlir::LogicalResult emitCXXForRangeStmt(const CXXForRangeStmt &s,
1981
1984
1986 const Expr *e, Address base, mlir::Value memberPtr,
1987 const MemberPointerType *memberPtrType, LValueBaseInfo *baseInfo);
1988
1990 const clang::CXXMethodDecl *md, const CIRGenCallee &callee,
1991 ReturnValueSlot returnValue, mlir::Value thisPtr,
1992 mlir::Value implicitParam, clang::QualType implicitParamTy,
1993 const clang::CallExpr *ce, CallArgList *rtlArgs);
1994
1996 const clang::CallExpr *ce, const clang::CXXMethodDecl *md,
1997 ReturnValueSlot returnValue, bool hasQualifier,
1998 clang::NestedNameSpecifier qualifier, bool isArrow,
1999 const clang::Expr *base);
2000
2003
2004 mlir::Value emitCXXNewExpr(const CXXNewExpr *e);
2005
2006 void emitNewArrayInitializer(const CXXNewExpr *e, QualType elementType,
2007 mlir::Type elementTy, Address beginPtr,
2008 mlir::Value numElements,
2009 mlir::Value allocSizeWithoutCookie);
2010
2011 /// Create a check for a function parameter that may potentially be
2012 /// declared as non-null.
2013 void emitNonNullArgCheck(RValue rv, QualType argType, SourceLocation argLoc,
2014 AbstractCallee ac, unsigned paramNum);
2015
2017 const CXXMethodDecl *md,
2019
2022
2024
2026 const CallExpr *callExpr,
2028
2029 void emitCXXTemporary(const CXXTemporary *temporary, QualType tempType,
2030 Address ptr);
2031
2032 void emitCXXThrowExpr(const CXXThrowExpr *e);
2033
2035 virtual mlir::LogicalResult operator()(CIRGenFunction &cgf) = 0;
2036 virtual ~cxxTryBodyEmitter() = default;
2037 };
2038
2039 void emitBeginCatch(const CXXCatchStmt *catchStmt, mlir::Value ehToken);
2040
2041 mlir::LogicalResult emitCXXTryStmt(const clang::CXXTryStmt &s,
2042 cxxTryBodyEmitter &bodyCallback);
2043 mlir::LogicalResult emitCXXTryStmt(const clang::CXXTryStmt &s);
2044
2046 clang::CXXCtorType ctorType, FunctionArgList &args);
2047
2048 // It's important not to confuse this and emitDelegateCXXConstructorCall.
2049 // Delegating constructors are the C++11 feature. The constructor delegate
2050 // optimization is used to reduce duplication in the base and complete
2051 // constructors where they are substantially the same.
2053 const FunctionArgList &args);
2054
2055 void emitDeleteCall(const FunctionDecl *deleteFD, mlir::Value ptr,
2056 QualType deleteTy);
2057
2058 mlir::LogicalResult emitDoStmt(const clang::DoStmt &s);
2059
2060 mlir::Value emitCXXTypeidExpr(const CXXTypeidExpr *e);
2061 mlir::Value emitDynamicCast(Address thisAddr, const CXXDynamicCastExpr *dce);
2062
2063 /// Emit an expression as an initializer for an object (variable, field, etc.)
2064 /// at the given location. The expression is not necessarily the normal
2065 /// initializer for the object, and the address is not necessarily
2066 /// its normal location.
2067 ///
2068 /// \param init the initializing expression
2069 /// \param d the object to act as if we're initializing
2070 /// \param lvalue the lvalue to initialize
2071 /// \param capturedByInit true if \p d is a __block variable whose address is
2072 /// potentially changed by the initializer
2073 void emitExprAsInit(const clang::Expr *init, const clang::ValueDecl *d,
2074 LValue lvalue, bool capturedByInit = false);
2075
2076 mlir::LogicalResult emitFunctionBody(const clang::Stmt *body);
2077
2078 mlir::LogicalResult emitGotoStmt(const clang::GotoStmt &s);
2079
2080 mlir::LogicalResult emitIndirectGotoStmt(const IndirectGotoStmt &s);
2081
2083
2085 clang::Expr *init);
2086
2088
2089 mlir::Value emitPromotedComplexExpr(const Expr *e, QualType promotionType);
2090
2091 mlir::Value emitPromotedScalarExpr(const Expr *e, QualType promotionType);
2092
2093 mlir::Value emitPromotedValue(mlir::Value result, QualType promotionType);
2094
2095 void emitReturnOfRValue(mlir::Location loc, RValue rv, QualType ty);
2096
2097 mlir::Value emitRuntimeCall(mlir::Location loc, cir::FuncOp callee,
2099 mlir::NamedAttrList attrs = {});
2100
2101 void emitInvariantStart(CharUnits size, mlir::Value addr, mlir::Location loc);
2102
2103 /// Emit the computation of the specified expression of scalar type.
2104 mlir::Value emitScalarExpr(const clang::Expr *e,
2105 bool ignoreResultAssign = false);
2106
2107 mlir::Value emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv);
2108
2109 /// Build a debug stoppoint if we are emitting debug info.
2110 void emitStopPoint(const Stmt *s);
2111
2112 // Build CIR for a statement. useCurrentScope should be true if no
2113 // new scopes need be created when finding a compound statement.
2114 mlir::LogicalResult emitStmt(const clang::Stmt *s, bool useCurrentScope,
2115 llvm::ArrayRef<const Attr *> attrs = {});
2116
2117 mlir::LogicalResult emitSimpleStmt(const clang::Stmt *s,
2118 bool useCurrentScope);
2119
2120 mlir::LogicalResult emitForStmt(const clang::ForStmt &s);
2121
2122 void emitForwardingCallToLambda(const CXXMethodDecl *lambdaCallOperator,
2123 CallArgList &callArgs);
2124
2125 RValue emitCoawaitExpr(const CoawaitExpr &e,
2126 AggValueSlot aggSlot = AggValueSlot::ignored(),
2127 bool ignoreResult = false);
2128
2129 RValue emitCoyieldExpr(const CoyieldExpr &e,
2130 AggValueSlot aggSlot = AggValueSlot::ignored(),
2131 bool ignoreResult = false);
2132 /// Emit the computation of the specified expression of complex type,
2133 /// returning the result.
2134 mlir::Value emitComplexExpr(const Expr *e);
2135
2136 void emitComplexExprIntoLValue(const Expr *e, LValue dest, bool isInit);
2137
2138 mlir::Value emitComplexPrePostIncDec(const UnaryOperator *e, LValue lv);
2139
2140 LValue emitComplexAssignmentLValue(const BinaryOperator *e);
2141 LValue emitComplexCompoundAssignmentLValue(const CompoundAssignOperator *e);
2142 LValue emitScalarCompoundAssignWithComplex(const CompoundAssignOperator *e,
2143 mlir::Value &result);
2144
2145 mlir::LogicalResult
2146 emitCompoundStmt(const clang::CompoundStmt &s, Address *lastValue = nullptr,
2147 AggValueSlot slot = AggValueSlot::ignored());
2148
2149 mlir::LogicalResult
2151 Address *lastValue = nullptr,
2152 AggValueSlot slot = AggValueSlot::ignored());
2153
2154 void emitDecl(const clang::Decl &d, bool evaluateConditionDecl = false);
2155 mlir::LogicalResult emitDeclStmt(const clang::DeclStmt &s);
2156 LValue emitDeclRefLValue(const clang::DeclRefExpr *e);
2157
2158 mlir::LogicalResult emitDefaultStmt(const clang::DefaultStmt &s,
2159 mlir::Type condType,
2160 bool buildingTopLevelCase);
2161
2163 clang::CXXCtorType ctorType,
2164 const FunctionArgList &args,
2166
2167 /// We are performing a delegate call; that is, the current function is
2168 /// delegating to another one. Produce a r-value suitable for passing the
2169 /// given parameter.
2170 void emitDelegateCallArg(CallArgList &args, const clang::VarDecl *param,
2172
2173 /// Emit an `if` on a boolean condition to the specified blocks.
2174 /// FIXME: Based on the condition, this might try to simplify the codegen of
2175 /// the conditional based on the branch.
2176 /// In the future, we may apply code generation simplifications here,
2177 /// similar to those used in classic LLVM codegen
2178 /// See `EmitBranchOnBoolExpr` for inspiration.
2179 mlir::LogicalResult emitIfOnBoolExpr(const clang::Expr *cond,
2180 const clang::Stmt *thenS,
2181 const clang::Stmt *elseS);
2182 cir::IfOp emitIfOnBoolExpr(const clang::Expr *cond,
2183 BuilderCallbackRef thenBuilder,
2184 mlir::Location thenLoc,
2185 BuilderCallbackRef elseBuilder,
2186 std::optional<mlir::Location> elseLoc = {});
2187
2188 mlir::Value emitOpOnBoolExpr(mlir::Location loc, const clang::Expr *cond);
2189
2190 LValue emitPointerToDataMemberBinaryExpr(const BinaryOperator *e);
2191
2192 mlir::LogicalResult emitLabel(const clang::LabelDecl &d);
2193 mlir::LogicalResult emitLabelStmt(const clang::LabelStmt &s);
2194
2195 void emitLambdaDelegatingInvokeBody(const CXXMethodDecl *md);
2196 void emitLambdaStaticInvokeBody(const CXXMethodDecl *md);
2197
2198 mlir::LogicalResult emitIfStmt(const clang::IfStmt &s);
2199
2200 /// Emit code to compute the specified expression,
2201 /// ignoring the result.
2202 void emitIgnoredExpr(const clang::Expr *e);
2203
2204 RValue emitLoadOfBitfieldLValue(LValue lv, SourceLocation loc);
2205
2206 /// Load a complex number from the specified l-value.
2207 mlir::Value emitLoadOfComplex(LValue src, SourceLocation loc);
2208
2209 RValue emitLoadOfExtVectorElementLValue(LValue lv);
2210
2211 /// Given an expression that represents a value lvalue, this method emits
2212 /// the address of the lvalue, then loads the result as an rvalue,
2213 /// returning the rvalue.
2214 RValue emitLoadOfLValue(LValue lv, SourceLocation loc);
2215
2216 Address emitLoadOfReference(LValue refLVal, mlir::Location loc,
2217 LValueBaseInfo *pointeeBaseInfo);
2218 LValue emitLoadOfReferenceLValue(Address refAddr, mlir::Location loc,
2219 QualType refTy, AlignmentSource source);
2220
2221 /// EmitLoadOfScalar - Load a scalar value from an address, taking
2222 /// care to appropriately convert from the memory representation to
2223 /// the LLVM value representation. The l-value must be a simple
2224 /// l-value.
2225 mlir::Value emitLoadOfScalar(LValue lvalue, SourceLocation loc);
2226 mlir::Value emitLoadOfScalar(Address addr, bool isVolatile, QualType ty,
2227 SourceLocation loc, LValueBaseInfo baseInfo,
2228 bool isNontemporal = false);
2229
2230 /// Emit code to compute a designator that specifies the location
2231 /// of the expression.
2232 /// FIXME: document this function better.
2233 LValue emitLValue(const clang::Expr *e);
2234 LValue emitLValueForBitField(LValue base, const FieldDecl *field);
2235 LValue emitLValueForField(LValue base, const clang::FieldDecl *field);
2236
2237 LValue emitLValueForLambdaField(const FieldDecl *field);
2238 LValue emitLValueForLambdaField(const FieldDecl *field,
2239 mlir::Value thisValue);
2240
2241 /// Like emitLValueForField, excpet that if the Field is a reference, this
2242 /// will return the address of the reference and not the address of the value
2243 /// stored in the reference.
2244 LValue emitLValueForFieldInitialization(LValue base,
2245 const clang::FieldDecl *field,
2246 llvm::StringRef fieldName);
2247
2248 LValue emitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *e);
2249
2250 LValue emitMemberExpr(const MemberExpr *e);
2251
2252 /// Emit a musttail call for a thunk with a potentially different ABI.
2253 void emitMustTailThunk(GlobalDecl gd, mlir::Value adjustedThisPtr,
2254 cir::FuncOp callee);
2255
2256 /// Emit a call to an AMDGPU builtin function.
2257 std::optional<mlir::Value> emitAMDGPUBuiltinExpr(unsigned builtinID,
2258 const CallExpr *expr);
2259
2260 /// Emit a call to an NVPTX builtin function.
2261 std::optional<mlir::Value> emitNVPTXBuiltinExpr(unsigned builtinID,
2262 const CallExpr *expr);
2263
2264 /// Emit a device-side printf call for NVPTX targets.
2265 mlir::Value emitNVPTXDevicePrintfCallExpr(const CallExpr *expr);
2266
2267 LValue emitOpaqueValueLValue(const OpaqueValueExpr *e);
2268
2269 LValue emitConditionalOperatorLValue(const AbstractConditionalOperator *expr);
2270
2271 /// Given an expression with a pointer type, emit the value and compute our
2272 /// best estimate of the alignment of the pointee.
2273 ///
2274 /// One reasonable way to use this information is when there's a language
2275 /// guarantee that the pointer must be aligned to some stricter value, and
2276 /// we're simply trying to ensure that sufficiently obvious uses of under-
2277 /// aligned objects don't get miscompiled; for example, a placement new
2278 /// into the address of a local variable. In such a case, it's quite
2279 /// reasonable to just ignore the returned alignment when it isn't from an
2280 /// explicit source.
2281 Address emitPointerWithAlignment(const clang::Expr *expr,
2282 LValueBaseInfo *baseInfo = nullptr);
2283
2284 /// Emits a reference binding to the passed in expression.
2285 RValue emitReferenceBindingToExpr(const Expr *e);
2286
2287 mlir::LogicalResult emitReturnStmt(const clang::ReturnStmt &s);
2288
2289 RValue emitRotate(const CallExpr *e, bool isRotateLeft);
2290
2291 mlir::Value emitScalarConstant(const ConstantEmission &constant, Expr *e);
2292
2293 /// Emit a conversion from the specified type to the specified destination
2294 /// type, both of which are CIR scalar types.
2295 mlir::Value emitScalarConversion(mlir::Value src, clang::QualType srcType,
2296 clang::QualType dstType,
2297 clang::SourceLocation loc);
2298
2299 void emitScalarInit(const clang::Expr *init, LValue lvalue,
2300 bool capturedByInit = false);
2301
2302 mlir::Value emitScalarOrConstFoldImmArg(unsigned iceArguments, unsigned idx,
2303 const Expr *argExpr);
2304
2305 void emitStaticVarDecl(const VarDecl &d, cir::GlobalLinkageKind linkage);
2306
2307 /// Emit a guarded initializer for a static local variable.
2308 void emitCXXGuardedInit(const VarDecl &varDecl, cir::GlobalOp globalOp,
2309 bool performInit);
2310
2311 void emitStoreOfComplex(mlir::Location loc, mlir::Value v, LValue dest,
2312 bool isInit);
2313
2314 void emitStoreOfScalar(mlir::Value value, Address addr, bool isVolatile,
2315 clang::QualType ty, LValueBaseInfo baseInfo,
2316 bool isInit = false, bool isNontemporal = false);
2317 void emitStoreOfScalar(mlir::Value value, LValue lvalue, bool isInit);
2318
2319 void emitStoreThroughExtVectorComponentLValue(RValue src, LValue dst);
2320
2321 /// Store the specified rvalue into the specified
2322 /// lvalue, where both are guaranteed to the have the same type, and that
2323 /// type is 'Ty'.
2324 void emitStoreThroughLValue(RValue src, LValue dst, bool isInit = false);
2325
2326 mlir::Value emitStoreThroughBitfieldLValue(RValue src, LValue dstresult);
2327
2328 LValue emitStringLiteralLValue(const StringLiteral *e,
2329 llvm::StringRef name = ".str");
2330
2331 mlir::LogicalResult emitSwitchBody(const clang::Stmt *s);
2332 mlir::LogicalResult emitSwitchCase(const clang::SwitchCase &s,
2333 bool buildingTopLevelCase);
2334 mlir::LogicalResult emitSwitchStmt(const clang::SwitchStmt &s);
2335
2336 mlir::LogicalResult emitSYCLKernelCallStmt(const SYCLKernelCallStmt &s);
2337
2338 void emitSYCLKernelCaller(const clang::OutlinedFunctionDecl *outlinedFnDecl,
2339 cir::FuncOp funcOp, cir::FuncType funcType,
2340 FunctionArgList &args);
2341
2342 /// Remove leftover empty and unreachable blocks from an emitted function.
2343 static void eraseEmptyAndUnusedBlocks(cir::FuncOp func);
2344
2345 std::optional<mlir::Value>
2346 emitTargetBuiltinExpr(unsigned builtinID, const clang::CallExpr *e,
2347 ReturnValueSlot &returnValue);
2348
2349 /// Given a value and its clang type, returns the value casted to its memory
2350 /// representation.
2351 /// Note: CIR defers most of the special casting to the final lowering passes
2352 /// to conserve the high level information.
2353 mlir::Value emitToMemory(mlir::Value value, clang::QualType ty);
2354
2355 /// EmitFromMemory - Change a scalar value from its memory
2356 /// representation to its value representation.
2357 mlir::Value emitFromMemory(mlir::Value value, clang::QualType ty);
2358
2359 /// Emit a trap instruction, which is used to abort the program in an abnormal
2360 /// way, usually for debugging purposes.
2361 /// \p createNewBlock indicates whether to create a new block for the IR
2362 /// builder. Since the `cir.trap` operation is a terminator, operations that
2363 /// follow a trap cannot be emitted after `cir.trap` in the same block. To
2364 /// ensure these operations get emitted successfully, you need to create a new
2365 /// dummy block and set the insertion point there before continuing from the
2366 /// trap operation.
2367 void emitTrap(mlir::Location loc, bool createNewBlock);
2368
2369 LValue emitUnaryOpLValue(const clang::UnaryOperator *e);
2370
2371 mlir::Value emitUnPromotedValue(mlir::Value result, QualType unPromotionType);
2372
2373 /// Emit a reached-unreachable diagnostic if \p loc is valid and runtime
2374 /// checking is enabled. Otherwise, just emit an unreachable instruction.
2375 /// \p createNewBlock indicates whether to create a new block for the IR
2376 /// builder. Since the `cir.unreachable` operation is a terminator, operations
2377 /// that follow an unreachable point cannot be emitted after `cir.unreachable`
2378 /// in the same block. To ensure these operations get emitted successfully,
2379 /// you need to create a dummy block and set the insertion point there before
2380 /// continuing from the unreachable point.
2381 void emitUnreachable(clang::SourceLocation loc, bool createNewBlock);
2382
2383 /// This method handles emission of any variable declaration
2384 /// inside a function, including static vars etc.
2385 void emitVarDecl(const clang::VarDecl &d);
2386
2387 void emitVariablyModifiedType(QualType ty);
2388
2389 mlir::LogicalResult emitWhileStmt(const clang::WhileStmt &s);
2390
2391 std::optional<mlir::Value> emitRISCVBuiltinExpr(unsigned builtinID,
2392 const CallExpr *expr);
2393 cir::GetGlobalOp createGetCpuModel(mlir::Location loc);
2394 cir::GetGlobalOp createGetCpuFeatures2(mlir::Location loc);
2395 mlir::Value emitX86CpuIs(const CallExpr *expr);
2396 mlir::Value emitX86CpuIs(mlir::Location loc, StringRef cpuStr);
2397 mlir::Value emitX86CpuSupports(const CallExpr *expr);
2398 mlir::Value emitX86CpuSupports(mlir::Location loc,
2399 ArrayRef<StringRef> FeatureStrs);
2400 mlir::Value emitX86CpuSupports(mlir::Location loc,
2401 std::array<uint32_t, 4> FeatureMask);
2402 mlir::Value emitX86CpuInit(mlir::Location loc);
2403 std::optional<mlir::Value> emitX86BuiltinExpr(unsigned builtinID,
2404 const CallExpr *expr);
2405
2406 /// Given an assignment `*lhs = rhs`, emit a test that checks if \p rhs is
2407 /// nonnull, if 1\p LHS is marked _Nonnull.
2408 void emitNullabilityCheck(LValue lhs, mlir::Value rhs,
2409 clang::SourceLocation loc);
2410
2411 /// An object to manage conditionally-evaluated expressions.
2413 CIRGenFunction &cgf;
2414 mlir::OpBuilder::InsertPoint insertPt;
2415
2416 public:
2418 : cgf(cgf), insertPt(cgf.builder.saveInsertionPoint()) {}
2419 ConditionalEvaluation(CIRGenFunction &cgf, mlir::OpBuilder::InsertPoint ip)
2420 : cgf(cgf), insertPt(ip) {}
2421
2423 assert(cgf.outermostConditional != this);
2424 if (!cgf.outermostConditional)
2425 cgf.outermostConditional = this;
2426 }
2427
2429 assert(cgf.outermostConditional != nullptr);
2430 if (cgf.outermostConditional == this)
2431 cgf.outermostConditional = nullptr;
2432 }
2433
2434 /// Returns the insertion point which will be executed prior to each
2435 /// evaluation of the conditional code. In LLVM OG, this method
2436 /// is called getStartingBlock.
2437 mlir::OpBuilder::InsertPoint getInsertPoint() const { return insertPt; }
2438 };
2439
2441 std::optional<LValue> lhs{}, rhs{};
2442 mlir::Value result{};
2443 };
2444
2445 // Return true if we're currently emitting one branch or the other of a
2446 // conditional expression.
2447 bool isInConditionalBranch() const { return outermostConditional != nullptr; }
2448
2449 void setBeforeOutermostConditional(mlir::Value value, Address addr) {
2450 assert(isInConditionalBranch());
2451 {
2452 mlir::OpBuilder::InsertionGuard guard(builder);
2453 builder.restoreInsertionPoint(outermostConditional->getInsertPoint());
2454 builder.createStore(
2455 value.getLoc(), value, addr, /*isVolatile=*/false,
2456 /*isNontemporal=*/false,
2457 mlir::IntegerAttr::get(
2458 mlir::IntegerType::get(value.getContext(), 64),
2459 (uint64_t)addr.getAlignment().getAsAlign().value()));
2460 }
2461 }
2462
2463 // Points to the outermost active conditional control. This is used so that
2464 // we know if a temporary should be destroyed conditionally.
2466
2467 /// An RAII object to record that we're evaluating a statement
2468 /// expression.
2470 CIRGenFunction &cgf;
2471
2472 /// We have to save the outermost conditional: cleanups in a
2473 /// statement expression aren't conditional just because the
2474 /// StmtExpr is.
2475 ConditionalEvaluation *savedOutermostConditional;
2476
2477 public:
2479 : cgf(cgf), savedOutermostConditional(cgf.outermostConditional) {
2480 cgf.outermostConditional = nullptr;
2481 }
2482
2484 cgf.outermostConditional = savedOutermostConditional;
2485 }
2486 };
2487
2488 template <typename FuncTy>
2489 ConditionalInfo emitConditionalBlocks(const AbstractConditionalOperator *e,
2490 const FuncTy &branchGenFunc);
2491
2492 mlir::Value emitTernaryOnBoolExpr(const clang::Expr *cond, mlir::Location loc,
2493 const clang::Stmt *thenS,
2494 const clang::Stmt *elseS);
2495
2496 /// Build a "reference" to a va_list; this is either the address or the value
2497 /// of the expression, depending on how va_list is defined.
2498 Address emitVAListRef(const Expr *e);
2499
2500 /// Emits the start of a CIR variable-argument operation (`cir.va_start`)
2501 ///
2502 /// \param vaList A reference to the \c va_list as emitted by either
2503 /// \c emitVAListRef or \c emitMSVAListRef.
2504 void emitVAStart(mlir::Value vaList);
2505
2506 /// Emits the end of a CIR variable-argument operation (`cir.va_start`)
2507 ///
2508 /// \param vaList A reference to the \c va_list as emitted by either
2509 /// \c emitVAListRef or \c emitMSVAListRef.
2510 void emitVAEnd(mlir::Value vaList);
2511
2512 /// Generate code to get an argument from the passed in pointer
2513 /// and update it accordingly.
2514 ///
2515 /// \param ve The \c VAArgExpr for which to generate code.
2516 ///
2517 /// \param vaListAddr Receives a reference to the \c va_list as emitted by
2518 /// either \c emitVAListRef or \c emitMSVAListRef.
2519 ///
2520 /// \returns SSA value with the argument.
2521 mlir::Value emitVAArg(VAArgExpr *ve);
2522
2523 /// ----------------------
2524 /// CIR build helpers
2525 /// -----------------
2526public:
2527 cir::AllocaOp createTempAlloca(mlir::Type ty, mlir::Location loc,
2528 const Twine &name = "tmp",
2529 mlir::Value arraySize = nullptr,
2530 bool insertIntoFnEntryBlock = false);
2531 cir::AllocaOp createTempAlloca(mlir::Type ty, mlir::Location loc,
2532 const Twine &name = "tmp",
2533 mlir::OpBuilder::InsertPoint ip = {},
2534 mlir::Value arraySize = nullptr);
2535 Address createTempAlloca(mlir::Type ty, CharUnits align, mlir::Location loc,
2536 const Twine &name = "tmp",
2537 mlir::Value arraySize = nullptr,
2538 Address *alloca = nullptr,
2539 mlir::OpBuilder::InsertPoint ip = {});
2540 Address createTempAlloca(mlir::Type ty,
2541 mlir::ptr::MemorySpaceAttrInterface destAddrSpace,
2542 CharUnits align, mlir::Location loc,
2543 const Twine &name = "tmp",
2544 mlir::Value arraySize = nullptr,
2545 Address *alloca = nullptr,
2546 mlir::OpBuilder::InsertPoint ip = {});
2547 Address createTempAllocaWithoutCast(mlir::Type ty, CharUnits align,
2548 mlir::Location loc,
2549 const Twine &name = "tmp",
2550 mlir::Value arraySize = nullptr,
2551 mlir::OpBuilder::InsertPoint ip = {});
2552 Address
2553 maybeCastStackAddressSpace(Address alloca,
2554 mlir::ptr::MemorySpaceAttrInterface destAddrSpace,
2555 mlir::Value arraySize = nullptr);
2556 Address createDefaultAlignTempAlloca(mlir::Type ty, mlir::Location loc,
2557 const Twine &name);
2558
2559 /// Create a temporary memory object of the given type, with
2560 /// appropriate alignmen and cast it to the default address space. Returns
2561 /// the original alloca instruction by \p Alloca if it is not nullptr.
2562 Address createMemTemp(QualType t, mlir::Location loc,
2563 const Twine &name = "tmp", Address *alloca = nullptr,
2564 mlir::OpBuilder::InsertPoint ip = {});
2565 Address createMemTemp(QualType t, CharUnits align, mlir::Location loc,
2566 const Twine &name = "tmp", Address *alloca = nullptr,
2567 mlir::OpBuilder::InsertPoint ip = {});
2568 Address createMemTempWithoutCast(QualType t, mlir::Location loc,
2569 const Twine &name = "tmp");
2570
2571 mlir::Value performAddrSpaceCast(mlir::Value v, mlir::Type destTy) const {
2572 if (cir::GlobalOp globalOp = v.getDefiningOp<cir::GlobalOp>())
2573 cgm.errorNYI("Global op addrspace cast");
2574 return builder.createAddrSpaceCast(v, destTy);
2575 }
2576
2577 //===--------------------------------------------------------------------===//
2578 // OpenMP Emission
2579 //===--------------------------------------------------------------------===//
2580public:
2581 mlir::LogicalResult emitOMPScopeDirective(const OMPScopeDirective &s);
2582 mlir::LogicalResult emitOMPErrorDirective(const OMPErrorDirective &s);
2583 mlir::LogicalResult emitOMPParallelDirective(const OMPParallelDirective &s);
2584 mlir::LogicalResult emitOMPTaskwaitDirective(const OMPTaskwaitDirective &s);
2585 mlir::LogicalResult emitOMPTaskyieldDirective(const OMPTaskyieldDirective &s);
2586 mlir::LogicalResult emitOMPBarrierDirective(const OMPBarrierDirective &s);
2587 mlir::LogicalResult emitOMPMetaDirective(const OMPMetaDirective &s);
2588 mlir::LogicalResult emitOMPCanonicalLoop(const OMPCanonicalLoop &s);
2589 mlir::LogicalResult emitOMPSimdDirective(const OMPSimdDirective &s);
2590 mlir::LogicalResult emitOMPTileDirective(const OMPTileDirective &s);
2591 mlir::LogicalResult emitOMPUnrollDirective(const OMPUnrollDirective &s);
2592 mlir::LogicalResult emitOMPFuseDirective(const OMPFuseDirective &s);
2593 mlir::LogicalResult emitOMPForDirective(const OMPForDirective &s);
2594 mlir::LogicalResult emitOMPForSimdDirective(const OMPForSimdDirective &s);
2595 mlir::LogicalResult emitOMPSectionsDirective(const OMPSectionsDirective &s);
2596 mlir::LogicalResult emitOMPSectionDirective(const OMPSectionDirective &s);
2597 mlir::LogicalResult emitOMPSingleDirective(const OMPSingleDirective &s);
2598 mlir::LogicalResult emitOMPMasterDirective(const OMPMasterDirective &s);
2599 mlir::LogicalResult emitOMPCriticalDirective(const OMPCriticalDirective &s);
2600 mlir::LogicalResult
2602 mlir::LogicalResult
2604 mlir::LogicalResult
2606 mlir::LogicalResult
2608 mlir::LogicalResult emitOMPTaskDirective(const OMPTaskDirective &s);
2609 mlir::LogicalResult emitOMPTaskgroupDirective(const OMPTaskgroupDirective &s);
2610 mlir::LogicalResult emitOMPFlushDirective(const OMPFlushDirective &s);
2611 mlir::LogicalResult emitOMPDepobjDirective(const OMPDepobjDirective &s);
2612 mlir::LogicalResult emitOMPScanDirective(const OMPScanDirective &s);
2613 mlir::LogicalResult
2615 mlir::LogicalResult
2617 mlir::LogicalResult emitOMPAtomicDirective(const OMPAtomicDirective &s);
2618 mlir::LogicalResult emitOMPTargetDirective(const OMPTargetDirective &s);
2619 mlir::LogicalResult emitOMPTeamsDirective(const OMPTeamsDirective &s);
2620 mlir::LogicalResult
2622 mlir::LogicalResult emitOMPCancelDirective(const OMPCancelDirective &s);
2623 mlir::LogicalResult
2625 mlir::LogicalResult
2627 mlir::LogicalResult
2629 mlir::LogicalResult
2631 mlir::LogicalResult
2633 mlir::LogicalResult emitOMPTaskLoopDirective(const OMPTaskLoopDirective &s);
2634 mlir::LogicalResult
2636 mlir::LogicalResult
2638 mlir::LogicalResult
2640 mlir::LogicalResult
2642 mlir::LogicalResult
2644 mlir::LogicalResult
2646 mlir::LogicalResult
2648 mlir::LogicalResult emitOMPParallelMaskedTaskLoopDirective(
2652 mlir::LogicalResult emitOMPParallelMasterTaskLoopDirective(
2656 mlir::LogicalResult
2658 mlir::LogicalResult emitOMPDistributeParallelForDirective(
2662 mlir::LogicalResult
2666 mlir::LogicalResult emitOMPTargetParallelForSimdDirective(
2668 mlir::LogicalResult
2670 mlir::LogicalResult emitOMPTargetTeamsGenericLoopDirective(
2672 mlir::LogicalResult
2674 mlir::LogicalResult
2676 mlir::LogicalResult
2682 mlir::LogicalResult
2684 mlir::LogicalResult
2686 mlir::LogicalResult emitOMPTargetTeamsDistributeDirective(
2694 mlir::LogicalResult emitOMPInteropDirective(const OMPInteropDirective &s);
2695 mlir::LogicalResult emitOMPDispatchDirective(const OMPDispatchDirective &s);
2696 mlir::LogicalResult
2698 mlir::LogicalResult emitOMPReverseDirective(const OMPReverseDirective &s);
2699 mlir::LogicalResult emitOMPSplitDirective(const OMPSplitDirective &s);
2700 mlir::LogicalResult
2702 mlir::LogicalResult emitOMPAssumeDirective(const OMPAssumeDirective &s);
2703 mlir::LogicalResult emitOMPMaskedDirective(const OMPMaskedDirective &s);
2704 mlir::LogicalResult emitOMPStripeDirective(const OMPStripeDirective &s);
2705
2709 void emitOMPAllocateDecl(const OMPAllocateDecl &d);
2712 void emitOMPRequiresDecl(const OMPRequiresDecl &d);
2713
2714 //===--------------------------------------------------------------------===//
2715 // OpenACC Emission
2716 //===--------------------------------------------------------------------===//
2717private:
2718 template <typename Op>
2719 Op emitOpenACCOp(mlir::Location start, OpenACCDirectiveKind dirKind,
2721 // Function to do the basic implementation of an operation with an Associated
2722 // Statement. Models AssociatedStmtConstruct.
2723 template <typename Op, typename TermOp>
2724 mlir::LogicalResult
2725 emitOpenACCOpAssociatedStmt(mlir::Location start, mlir::Location end,
2726 OpenACCDirectiveKind dirKind,
2728 const Stmt *associatedStmt);
2729
2730 template <typename Op, typename TermOp>
2731 mlir::LogicalResult emitOpenACCOpCombinedConstruct(
2732 mlir::Location start, mlir::Location end, OpenACCDirectiveKind dirKind,
2733 llvm::ArrayRef<const OpenACCClause *> clauses, const Stmt *loopStmt);
2734
2735 template <typename Op>
2736 void emitOpenACCClauses(Op &op, OpenACCDirectiveKind dirKind,
2738 // The second template argument doesn't need to be a template, since it should
2739 // always be an mlir::acc::LoopOp, but as this is a template anyway, we make
2740 // it a template argument as this way we can avoid including the OpenACC MLIR
2741 // headers here. We will count on linker failures/explicit instantiation to
2742 // ensure we don't mess this up, but it is only called from 1 place, and
2743 // instantiated 3x.
2744 template <typename ComputeOp, typename LoopOp>
2745 void emitOpenACCClauses(ComputeOp &op, LoopOp &loopOp,
2746 OpenACCDirectiveKind dirKind,
2748
2749 // The OpenACC LoopOp requires that we have auto, seq, or independent on all
2750 // LoopOp operations for the 'none' device type case. This function checks if
2751 // the LoopOp has one, else it updates it to have one.
2752 void updateLoopOpParallelism(mlir::acc::LoopOp &op, bool isOrphan,
2754
2755 // The OpenACC 'cache' construct actually applies to the 'loop' if present. So
2756 // keep track of the 'loop' so that we can add the cache vars to it correctly.
2757 mlir::acc::LoopOp *activeLoopOp = nullptr;
2758
2759 struct ActiveOpenACCLoopRAII {
2760 CIRGenFunction &cgf;
2761 mlir::acc::LoopOp *oldLoopOp;
2762
2763 ActiveOpenACCLoopRAII(CIRGenFunction &cgf, mlir::acc::LoopOp *newOp)
2764 : cgf(cgf), oldLoopOp(cgf.activeLoopOp) {
2765 cgf.activeLoopOp = newOp;
2766 }
2767 ~ActiveOpenACCLoopRAII() { cgf.activeLoopOp = oldLoopOp; }
2768 };
2769
2770 // Keep track of the last place we inserted a 'recipe' so that we can insert
2771 // the next one in lexical order.
2772 mlir::OpBuilder::InsertPoint lastRecipeLocation;
2773
2774public:
2775 // Helper type used to store the list of important information for a 'data'
2776 // clause variable, or a 'cache' variable reference.
2778 mlir::Location beginLoc;
2779 mlir::Value varValue;
2780 std::string name;
2781 // The type of the original variable reference: that is, after 'bounds' have
2782 // removed pointers/array types/etc. So in the case of int arr[5], and a
2783 // private(arr[1]), 'origType' is 'int', but 'baseType' is 'int[5]'.
2787 // The list of types that we found when going through the bounds, which we
2788 // can use to properly set the alloca section.
2790 };
2791
2792 // Gets the collection of info required to lower and OpenACC clause or cache
2793 // construct variable reference.
2795 // Helper function to emit the integer expressions as required by an OpenACC
2796 // clause/construct.
2797 mlir::Value emitOpenACCIntExpr(const Expr *intExpr);
2798 // Helper function to emit an integer constant as an mlir int type, used for
2799 // constants in OpenACC constructs/clauses.
2800 mlir::Value createOpenACCConstantInt(mlir::Location loc, unsigned width,
2801 int64_t value);
2802
2803 mlir::LogicalResult
2805 mlir::LogicalResult emitOpenACCLoopConstruct(const OpenACCLoopConstruct &s);
2806 mlir::LogicalResult
2808 mlir::LogicalResult emitOpenACCDataConstruct(const OpenACCDataConstruct &s);
2809 mlir::LogicalResult
2811 mlir::LogicalResult
2813 mlir::LogicalResult
2815 mlir::LogicalResult emitOpenACCWaitConstruct(const OpenACCWaitConstruct &s);
2816 mlir::LogicalResult emitOpenACCInitConstruct(const OpenACCInitConstruct &s);
2817 mlir::LogicalResult
2819 mlir::LogicalResult emitOpenACCSetConstruct(const OpenACCSetConstruct &s);
2820 mlir::LogicalResult
2822 mlir::LogicalResult
2824 mlir::LogicalResult emitOpenACCCacheConstruct(const OpenACCCacheConstruct &s);
2825
2828
2829 /// Create a temporary memory object for the given aggregate type.
2830 AggValueSlot createAggTemp(QualType ty, mlir::Location loc,
2831 const Twine &name = "tmp",
2832 Address *alloca = nullptr) {
2834 return AggValueSlot::forAddr(
2835 createMemTemp(ty, loc, name, alloca), ty.getQualifiers(),
2838 }
2839
2840private:
2841 QualType getVarArgType(const Expr *arg);
2842
2843 bool shouldEmitLifetimeMarkers = false;
2844 /// Set when the current function has a goto/switch that may bypass a local's
2845 /// init; lifetime markers are then suppressed. See functionMightHaveBypass.
2846 bool fnHasBypassStmt = false;
2847
2848 bool shouldEmitLifetimeMarkersForAutoVar() const {
2849 return shouldEmitLifetimeMarkers && !fnHasBypassStmt;
2850 }
2851
2852 class InlinedInheritingConstructorScope {
2853 public:
2854 InlinedInheritingConstructorScope(CIRGenFunction &cgf, GlobalDecl gd)
2855 : cgf(cgf), oldCurGD(cgf.curGD), oldCurFuncDecl(cgf.curFuncDecl),
2856 oldCurCodeDecl(cgf.curCodeDecl),
2857 oldCxxabiThisDecl(cgf.cxxabiThisDecl),
2858 oldCxxThisValue(cgf.cxxThisValue),
2859 oldCxxabiThisAlignment(cgf.cxxabiThisAlignment),
2860 oldCxxThisAlignment(cgf.cxxThisAlignment),
2861 oldReturnValue(cgf.returnValue), oldFnRetTy(cgf.fnRetTy),
2862 oldCxxInheritedCtorInitExprArgs(
2863 std::move(cgf.cxxInheritedCtorInitExprArgs)) {
2864 cgf.curGD = gd;
2865 cgf.curFuncDecl = cast<CXXConstructorDecl>(gd.getDecl());
2866 cgf.curCodeDecl = cgf.curFuncDecl;
2867 cgf.cxxabiThisDecl = nullptr;
2868 cgf.cxxabiThisValue = nullptr;
2869 cgf.cxxThisValue = nullptr;
2870 cgf.cxxThisAlignment = CharUnits();
2871 cgf.cxxabiThisAlignment = CharUnits();
2872 cgf.returnValue = Address::invalid();
2873 cgf.fnRetTy = QualType();
2874 cgf.cxxInheritedCtorInitExprArgs.clear();
2875 // FIXME: at one point when we want to call one of these, we'll need
2876 // CXXInheritedCtorInitExprArgs here too.
2877 }
2878 ~InlinedInheritingConstructorScope() {
2879 cgf.curGD = oldCurGD;
2880 cgf.curFuncDecl = oldCurFuncDecl;
2881 cgf.curCodeDecl = oldCurCodeDecl;
2882 cgf.cxxabiThisDecl = oldCxxabiThisDecl;
2883 cgf.cxxabiThisValue = oldCxxabiThisValue;
2884 cgf.cxxThisValue = oldCxxThisValue;
2885 cgf.cxxThisAlignment = oldCxxThisAlignment;
2886 cgf.cxxabiThisAlignment = oldCxxabiThisAlignment;
2887 cgf.returnValue = oldReturnValue;
2888 cgf.fnRetTy = oldFnRetTy;
2889 cgf.cxxInheritedCtorInitExprArgs =
2890 std::move(oldCxxInheritedCtorInitExprArgs);
2891 }
2892
2893 private:
2894 CIRGenFunction &cgf;
2895 GlobalDecl oldCurGD;
2896 const Decl *oldCurFuncDecl;
2897 const Decl *oldCurCodeDecl;
2898 ImplicitParamDecl *oldCxxabiThisDecl;
2899 mlir::Value oldCxxabiThisValue;
2900 mlir::Value oldCxxThisValue;
2901 clang::CharUnits oldCxxabiThisAlignment;
2902 clang::CharUnits oldCxxThisAlignment;
2903 Address oldReturnValue;
2904 QualType oldFnRetTy;
2905 CallArgList oldCxxInheritedCtorInitExprArgs;
2906 };
2907};
2908
2909} // namespace clang::CIRGen
2910
2911#endif
Defines the clang::ASTContext interface.
llvm::function_ref< void(mlir::OpBuilder &, mlir::Location)> BuilderCallbackRef
Definition CIRDialect.h:37
static void emitAtomicOp(CIRGenFunction &cgf, AtomicExpr *expr, Address dest, Address ptr, Address val1, Address val2, Expr *isWeakExpr, Expr *failureOrderExpr, int64_t size, cir::MemOrder order, cir::SyncScopeKind scope)
Defines the clang::Expr interface and subclasses for C++ expressions.
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.
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:3800
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.
ConditionalEvaluation(CIRGenFunction &cgf, mlir::OpBuilder::InsertPoint ip)
mlir::OpBuilder::InsertPoint getInsertPoint() const
Returns the insertion point which will be executed prior to each evaluation of the conditional code.
static ConstantEmission forReference(mlir::TypedAttr c)
static ConstantEmission forValue(mlir::TypedAttr c)
LValue getReferenceLValue(CIRGenFunction &cgf, Expr *refExpr) const
DeclMapRevertingRAII(CIRGenFunction &cgf, const VarDecl *vd)
Captures 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.
mlir::LogicalResult emitOMPTargetParallelForDirective(const OMPTargetParallelForDirective &s)
LValue emitCXXBindTemporaryLValue(const CXXBindTemporaryExpr *e)
mlir::LogicalResult emitOMPParallelMasterTaskLoopSimdDirective(const OMPParallelMasterTaskLoopSimdDirective &s)
mlir::LogicalResult emitOMPSimdDirective(const OMPSimdDirective &s)
mlir::Value emitCheckedArgForAssume(const Expr *e)
Emits an argument for a call to a __builtin_assume.
LValue emitOpaqueValueLValue(const OpaqueValueExpr *e)
mlir::LogicalResult emitDoStmt(const clang::DoStmt &s)
mlir::LogicalResult emitOMPCriticalDirective(const OMPCriticalDirective &s)
static cir::TypeEvaluationKind getEvaluationKind(clang::QualType type)
Return the cir::TypeEvaluationKind of QualType type.
clang::GlobalDecl curGD
The GlobalDecl for the current function being compiled or the global variable currently being initial...
clang::CurrentSourceLocExprScope::SourceLocExprScopeGuard SourceLocExprScopeGuard
RValue convertTempToRValue(Address addr, clang::QualType type, clang::SourceLocation loc)
Given the address of a temporary variable, produce an r-value of its type.
mlir::LogicalResult emitCoreturnStmt(const CoreturnStmt &s)
mlir::LogicalResult emitOpenACCDataConstruct(const OpenACCDataConstruct &s)
AutoVarEmission emitAutoVarAlloca(const clang::VarDecl &d, mlir::OpBuilder::InsertPoint ip={})
mlir::Value emitPromotedValue(mlir::Value result, QualType promotionType)
void emitAutoVarTypeCleanup(const AutoVarEmission &emission, clang::QualType::DestructionKind dtorKind)
Enter a destroy cleanup for the given local variable.
ImplicitParamDecl * cxxabiThisDecl
CXXThisDecl - When generating code for a C++ member function, this will hold the implicit 'this' decl...
EHScopeStack::stable_iterator prologueCleanupDepth
The cleanup depth enclosing all the cleanups associated with the parameters.
mlir::LogicalResult emitOpenACCCombinedConstruct(const OpenACCCombinedConstruct &s)
Address emitCXXMemberDataPointerAddress(const Expr *e, Address base, mlir::Value memberPtr, const MemberPointerType *memberPtrType, LValueBaseInfo *baseInfo)
bool curFuncIsThunk
In C++, whether we are code generating a thunk.
mlir::LogicalResult emitOMPParallelMasterDirective(const OMPParallelMasterDirective &s)
mlir::LogicalResult emitOpenACCWaitConstruct(const OpenACCWaitConstruct &s)
cir::FuncOp generateCode(clang::GlobalDecl gd, cir::FuncOp fn, cir::FuncType funcType)
llvm::SmallVector< PendingCleanupEntry > lifetimeExtendedCleanupStack
mlir::LogicalResult emitOMPCancellationPointDirective(const OMPCancellationPointDirective &s)
mlir::LogicalResult emitOMPParallelMaskedTaskLoopDirective(const OMPParallelMaskedTaskLoopDirective &s)
CIRGenTypes & getTypes() const
Address emitPointerWithAlignment(const clang::Expr *expr, LValueBaseInfo *baseInfo=nullptr)
Given an expression with a pointer type, emit the value and compute our best estimate of the alignmen...
llvm::ScopedHashTable< const clang::Decl *, mlir::Value > SymTableTy
The symbol table maps a variable name to a value in the current scope.
void initFullExprCleanup()
Set up the last cleanup that was pushed as a conditional full-expression cleanup.
void emitInvariantStart(CharUnits size, mlir::Value addr, mlir::Location loc)
Definition CIRGenCXX.cpp:33
mlir::LogicalResult emitOMPReverseDirective(const OMPReverseDirective &s)
void emitVariablyModifiedType(QualType ty)
RValue emitLoadOfLValue(LValue lv, SourceLocation loc)
Given an expression that represents a value lvalue, this method emits the address of the lvalue,...
const clang::LangOptions & getLangOpts() const
cir::AllocaOp createTempAlloca(mlir::Type ty, mlir::Location loc, const Twine &name="tmp", mlir::Value arraySize=nullptr, bool insertIntoFnEntryBlock=false)
This creates an alloca and inserts it into the entry block if ArraySize is nullptr,...
void emitTrap(mlir::Location loc, bool createNewBlock)
Emit a trap instruction, which is used to abort the program in an abnormal way, usually for debugging...
void emitForwardingCallToLambda(const CXXMethodDecl *lambdaCallOperator, CallArgList &callArgs)
mlir::Block * getCurFunctionEntryBlock()
void emitLoopConditionCleanups(EHScopeStack::stable_iterator depth, mlir::Location loc)
Emit the cleanups captured for a loop's condition variable (those pushed above depth while EHScopeSta...
RValue emitCXXMemberCallExpr(const clang::CXXMemberCallExpr *e, ReturnValueSlot returnValue)
mlir::LogicalResult emitOpenACCUpdateConstruct(const OpenACCUpdateConstruct &s)
RValue emitCXXMemberPointerCallExpr(const CXXMemberCallExpr *ce, ReturnValueSlot returnValue)
mlir::Value emitX86CpuIs(const CallExpr *expr)
LValue emitLValueForBitField(LValue base, const FieldDecl *field)
mlir::LogicalResult emitOMPTileDirective(const OMPTileDirective &s)
mlir::LogicalResult emitIfOnBoolExpr(const clang::Expr *cond, const clang::Stmt *thenS, const clang::Stmt *elseS)
Emit an if on a boolean condition to the specified blocks.
void emitOMPRequiresDecl(const OMPRequiresDecl &d)
VlaSizePair getVLASize(const VariableArrayType *type)
Returns an MLIR::Value+QualType pair that corresponds to the size, in non-variably-sized elements,...
LValue emitScalarCompoundAssignWithComplex(const CompoundAssignOperator *e, mlir::Value &result)
cir::CoroAllocOp emitCoroAllocBuiltinCall(const CallExpr *e)
mlir::LogicalResult emitOMPTargetTeamsDirective(const OMPTargetTeamsDirective &s)
Address cxxDefaultInitExprThis
The value of 'this' to sue when evaluating CXXDefaultInitExprs within this expression.
void emitStaticVarDecl(const VarDecl &d, cir::GlobalLinkageKind linkage)
mlir::Value emitComplexExpr(const Expr *e)
Emit the computation of the specified expression of complex type, returning the result.
mlir::LogicalResult emitOMPTeamsDistributeParallelForDirective(const OMPTeamsDistributeParallelForDirective &s)
mlir::LogicalResult emitOMPBarrierDirective(const OMPBarrierDirective &s)
void setBeforeOutermostConditional(mlir::Value value, Address addr)
mlir::LogicalResult emitOMPTargetParallelDirective(const OMPTargetParallelDirective &s)
mlir::LogicalResult emitOpenACCCacheConstruct(const OpenACCCacheConstruct &s)
mlir::Value loadCXXThis()
Load the value for 'this'.
LValue makeNaturalAlignPointeeAddrLValue(mlir::Value v, clang::QualType t)
Given a value of type T* that may not be to a complete object, construct an l-vlaue withi the natural...
RValue emitCallExpr(const clang::CallExpr *e, ReturnValueSlot returnValue=ReturnValueSlot())
void emitDeleteCall(const FunctionDecl *deleteFD, mlir::Value ptr, QualType deleteTy)
LValue emitMemberExpr(const MemberExpr *e)
const TargetInfo & getTarget() const
void replaceAddrOfLocalVar(const clang::VarDecl *vd, Address addr)
llvm::DenseMap< const clang::Decl *, Address > DeclMapTy
LValue emitConditionalOperatorLValue(const AbstractConditionalOperator *expr)
LValue emitLValue(const clang::Expr *e)
Emit code to compute a designator that specifies the location of the expression.
void addCatchHandlerAttr(const CXXCatchStmt *catchStmt, SmallVector< mlir::Attribute > &handlerAttrs)
Address makeNaturalAddressForPointer(mlir::Value ptr, QualType t, CharUnits alignment, bool forPointeeType=false, LValueBaseInfo *baseInfo=nullptr)
Construct an address with the natural alignment of T.
const clang::Decl * curFuncDecl
mlir::LogicalResult emitOMPTargetDirective(const OMPTargetDirective &s)
mlir::LogicalResult emitCXXForRangeStmt(const CXXForRangeStmt &s, llvm::ArrayRef< const Attr * > attrs)
LValue emitLValueForLambdaField(const FieldDecl *field)
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.
LValue emitComplexCompoundAssignmentLValue(const CompoundAssignOperator *e)
mlir::LogicalResult emitOMPScopeDirective(const OMPScopeDirective &s)
void emitBeginCatch(const CXXCatchStmt *catchStmt, mlir::Value ehToken)
Begins a catch statement by initializing the catch variable and calling __cxa_begin_catch.
mlir::Value getVTTParameter(GlobalDecl gd, bool forVirtualBase, bool delegating)
Return the VTT parameter that should be passed to a base constructor/destructor with virtual bases.
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
mlir::LogicalResult emitOMPDepobjDirective(const OMPDepobjDirective &s)
void initializeVTablePointers(mlir::Location loc, const clang::CXXRecordDecl *rd)
mlir::Type convertType(const TypeDecl *t)
bool constantFoldsToBool(const clang::Expr *cond, bool &resultBool, bool allowLabels=false)
If the specified expression does not fold to a constant, or if it does but contains a label,...
mlir::Value emitOpOnBoolExpr(mlir::Location loc, const clang::Expr *cond)
TODO(cir): see EmitBranchOnBoolExpr for extra ideas).
void emitLoopConditionVariable(const clang::VarDecl &d, DeferredLoopConditionCleanup &condCleanup)
Emit a loop's condition-variable declaration.
void emitStoreThroughExtVectorComponentLValue(RValue src, LValue dst)
void initializeVTablePointer(mlir::Location loc, const VPtr &vptr)
Address getAddressOfBaseClass(Address value, const CXXRecordDecl *derived, llvm::iterator_range< CastExpr::path_const_iterator > path, bool nullCheckValue, SourceLocation loc)
void emitOMPDeclareReduction(const OMPDeclareReductionDecl &d)
void emitAggregateStore(mlir::Value value, Address dest)
mlir::LogicalResult emitReturnStmt(const clang::ReturnStmt &s)
LValue emitLoadOfReferenceLValue(Address refAddr, mlir::Location loc, QualType refTy, AlignmentSource source)
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.
mlir::LogicalResult emitOMPDistributeParallelForSimdDirective(const OMPDistributeParallelForSimdDirective &s)
void emitBaseInitializer(mlir::Location loc, const CXXRecordDecl *classDecl, CXXCtorInitializer *baseInit)
RValue emitAtomicExpr(AtomicExpr *e)
void emitExprAsInit(const clang::Expr *init, const clang::ValueDecl *d, LValue lvalue, bool capturedByInit=false)
Emit an expression as an initializer for an object (variable, field, etc.) at the given location.
void emitCXXGuardedInit(const VarDecl &varDecl, cir::GlobalOp globalOp, bool performInit)
Emit a guarded initializer for a static local variable.
mlir::LogicalResult emitOMPUnrollDirective(const OMPUnrollDirective &s)
mlir::Value emitArrayLength(const clang::ArrayType *arrayType, QualType &baseType, Address &addr)
Computes the length of an array in elements, as well as the base element type and a properly-typed fi...
void emitNullInitialization(mlir::Location loc, Address destPtr, QualType ty)
mlir::LogicalResult emitOMPTaskDirective(const OMPTaskDirective &s)
mlir::LogicalResult emitOpenACCSetConstruct(const OpenACCSetConstruct &s)
mlir::Value performAddrSpaceCast(mlir::Value v, mlir::Type destTy) const
RValue emitReferenceBindingToExpr(const Expr *e)
Emits a reference binding to the passed in expression.
mlir::LogicalResult emitOMPTeamsGenericLoopDirective(const OMPTeamsGenericLoopDirective &s)
llvm::SmallVector< DeferredDeactivateCleanup > deferredDeactivationCleanupStack
VPtrsVector getVTablePointers(const clang::CXXRecordDecl *vtableClass)
const TargetCIRGenInfo & getTargetHooks() const
mlir::LogicalResult emitOMPCanonicalLoop(const OMPCanonicalLoop &s)
mlir::LogicalResult emitSwitchStmt(const clang::SwitchStmt &s)
RValue emitCoyieldExpr(const CoyieldExpr &e, AggValueSlot aggSlot=AggValueSlot::ignored(), bool ignoreResult=false)
cir::CoroFreeOp emitCoroFreeBuiltin(const CallExpr *e)
mlir::Value evaluateOrEmitBuiltinObjectSize(const clang::Expr *e, unsigned type, cir::IntType resType, mlir::Value emittedE, bool isDynamic)
mlir::LogicalResult emitOMPTeamsDirective(const OMPTeamsDirective &s)
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)
mlir::LogicalResult emitOMPMaskedTaskLoopDirective(const OMPMaskedTaskLoopDirective &s)
CleanupKind getCleanupKind(QualType::DestructionKind kind)
clang::CharUnits cxxabiThisAlignment
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)
mlir::LogicalResult emitOMPFuseDirective(const OMPFuseDirective &s)
AggValueSlot::Overlap_t getOverlapForFieldInit(const FieldDecl *fd)
mlir::LogicalResult emitSimpleStmt(const clang::Stmt *s, bool useCurrentScope)
mlir::LogicalResult emitOMPSectionDirective(const OMPSectionDirective &s)
mlir::Operation * curFn
The current function or global initializer that is generated code for.
mlir::LogicalResult emitAsmStmt(const clang::AsmStmt &s)
std::pair< mlir::Value, mlir::Type > emitAsmInputLValue(const TargetInfo::ConstraintInfo &info, LValue inputValue, QualType inputType, std::string &constraintString, SourceLocation loc)
Address emitExtVectorElementLValue(LValue lv, mlir::Location loc)
Generates lvalue for partial ext_vector access.
mlir::LogicalResult emitOMPParallelForSimdDirective(const OMPParallelForSimdDirective &s)
void emitOMPAllocateDecl(const OMPAllocateDecl &d)
mlir::LogicalResult emitOMPDistributeParallelForDirective(const OMPDistributeParallelForDirective &s)
mlir::Value emitScalarConversion(mlir::Value src, clang::QualType srcType, clang::QualType dstType, clang::SourceLocation loc)
Emit a conversion from the specified type to the specified destination type, both of which are CIR sc...
Address getAddressOfDerivedClass(mlir::Location loc, Address baseAddr, const CXXRecordDecl *derived, llvm::iterator_range< CastExpr::path_const_iterator > path, bool nullCheckValue)
mlir::LogicalResult emitOMPOrderedStandaloneDirective(const OMPOrderedStandaloneDirective &s)
std::optional< mlir::Value > emitTargetBuiltinExpr(unsigned builtinID, const clang::CallExpr *e, ReturnValueSlot &returnValue)
CallArgList cxxInheritedCtorInitExprArgs
The values of function arguments to use when evaluating CXXInheritedCtorInitExprs within this context...
mlir::Value emitPromotedComplexExpr(const Expr *e, QualType promotionType)
ImplicitParamDecl * cxxStructorImplicitParamDecl
When generating code for a constructor or destructor, this will hold the implicit argument (e....
mlir::LogicalResult emitOpenACCComputeConstruct(const OpenACCComputeConstruct &s)
void emitOMPDeclareMapper(const OMPDeclareMapperDecl &d)
mlir::LogicalResult emitOMPMasterTaskLoopSimdDirective(const OMPMasterTaskLoopSimdDirective &s)
EHScopeStack ehStack
Tracks function scope overall cleanup handling.
void enterDtorCleanups(const CXXDestructorDecl *dtor, CXXDtorType type)
Enter the cleanups necessary to complete the given phase of destruction for a destructor.
Address maybeCastStackAddressSpace(Address alloca, mlir::ptr::MemorySpaceAttrInterface destAddrSpace, mlir::Value arraySize=nullptr)
llvm::SmallVector< const ParmVarDecl * > fnArgs
Save Parameter Decl for coroutine.
mlir::Value emitUnPromotedValue(mlir::Value result, QualType unPromotionType)
mlir::LogicalResult emitSwitchBody(const clang::Stmt *s)
void startThunk(cir::FuncOp fn, GlobalDecl gd, const CIRGenFunctionInfo &fnInfo, bool isUnprototyped)
Start generating a thunk function.
RValue emitAtomicLoad(LValue lvalue, SourceLocation loc, AggValueSlot slot=AggValueSlot::ignored())
mlir::LogicalResult emitForStmt(const clang::ForStmt &s)
AggValueSlot createAggTemp(QualType ty, mlir::Location loc, const Twine &name="tmp", Address *alloca=nullptr)
Create a temporary memory object for the given aggregate type.
llvm::SmallVector< PendingCleanupEntry > deferredConditionalCleanupStack
void emitNewArrayInitializer(const CXXNewExpr *e, QualType elementType, mlir::Type elementTy, Address beginPtr, mlir::Value numElements, mlir::Value allocSizeWithoutCookie)
mlir::LogicalResult emitOMPTaskwaitDirective(const OMPTaskwaitDirective &s)
mlir::LogicalResult emitOMPFlushDirective(const OMPFlushDirective &s)
mlir::LogicalResult emitOMPGenericLoopDirective(const OMPGenericLoopDirective &s)
mlir::LogicalResult emitOMPTargetUpdateDirective(const OMPTargetUpdateDirective &s)
std::optional< mlir::Value > fnRetAlloca
The compiler-generated variable that holds the return value.
void emitImplicitAssignmentOperatorBody(FunctionArgList &args)
clang::SanitizerSet sanOpts
Sanitizers enabled for this function.
static int64_t getZExtIntValueFromConstOp(mlir::Value val)
Get zero-extended integer from a mlir::Value that is an int constant or a constant op.
mlir::LogicalResult emitOMPTargetParallelForSimdDirective(const OMPTargetParallelForSimdDirective &s)
mlir::LogicalResult emitOMPInterchangeDirective(const OMPInterchangeDirective &s)
RValue emitLoadOfExtVectorElementLValue(LValue lv)
mlir::Value emitCXXTypeidExpr(const CXXTypeidExpr *e)
mlir::LogicalResult emitOMPDispatchDirective(const OMPDispatchDirective &s)
mlir::Type convertTypeForMem(QualType t)
mlir::LogicalResult emitCXXTryStmt(const clang::CXXTryStmt &s, cxxTryBodyEmitter &bodyCallback)
clang::QualType buildFunctionArgList(clang::GlobalDecl gd, FunctionArgList &args)
mlir::LogicalResult emitOMPParallelDirective(const OMPParallelDirective &s)
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)
mlir::LogicalResult emitOMPForSimdDirective(const OMPForSimdDirective &s)
LValue emitAggExprToLValue(const Expr *e)
mlir::LogicalResult emitOMPTaskLoopDirective(const OMPTaskLoopDirective &s)
void emitStoreOfScalar(mlir::Value value, Address addr, bool isVolatile, clang::QualType ty, LValueBaseInfo baseInfo, bool isInit=false, bool isNontemporal=false)
void pushDestroy(QualType::DestructionKind dtorKind, Address addr, QualType type)
Push the standard destructor for the given type as at least a normal cleanup.
clang::CurrentSourceLocExprScope curSourceLocExprScope
Source location information about the default argument or member initializer expression we're evaluat...
mlir::Value loadCXXVTT()
Load the VTT parameter to base constructors/destructors have virtual bases.
void emitVarDecl(const clang::VarDecl &d)
This method handles emission of any variable declaration inside a function, including static vars etc...
LValue emitCompoundAssignmentLValue(const clang::CompoundAssignOperator *e)
mlir::Value emitSVEPredicateCast(mlir::Value pred, unsigned minNumElts, mlir::Location loc)
mlir::Value emitCXXNewExpr(const CXXNewExpr *e)
RValue getUndefRValue(clang::QualType ty)
Get an appropriate 'undef' rvalue for the given type.
bool getAArch64SVEProcessedOperands(unsigned builtinID, const CallExpr *expr, SmallVectorImpl< mlir::Value > &ops, clang::SVETypeFlags typeFlags)
Address returnValue
The temporary alloca to hold the return value.
LValue makeAddrLValue(Address addr, QualType ty, LValueBaseInfo baseInfo)
static int64_t getSExtIntValueFromConstOp(mlir::Value val)
Get integer from a mlir::Value that is an int constant or a constant op.
mlir::Value getArrayInitIndex()
Get the index of the current ArrayInitLoopExpr, if any.
mlir::LogicalResult emitOMPTargetDataDirective(const OMPTargetDataDirective &s)
std::optional< mlir::Value > emitX86BuiltinExpr(unsigned builtinID, const CallExpr *expr)
mlir::LogicalResult emitLabel(const clang::LabelDecl &d)
void emitCXXConstructorCall(const clang::CXXConstructorDecl *d, clang::CXXCtorType type, bool forVirtualBase, bool delegating, AggValueSlot thisAVS, const clang::CXXConstructExpr *e)
mlir::LogicalResult emitOMPTargetParallelGenericLoopDirective(const OMPTargetParallelGenericLoopDirective &s)
static bool hasAggregateEvaluationKind(clang::QualType type)
mlir::Value getVTablePtr(mlir::Location loc, Address thisAddr, const clang::CXXRecordDecl *vtableClass)
Return the Value of the vtable pointer member pointed to by thisAddr.
void emitArrayDestroy(mlir::Value begin, mlir::Value numElements, QualType elementType, CharUnits elementAlign, Destroyer *destroyer)
Destroys all the elements of the given array, beginning from last to first.
LValue emitPointerToDataMemberBinaryExpr(const BinaryOperator *e)
mlir::LogicalResult emitOMPParallelMaskedDirective(const OMPParallelMaskedDirective &s)
RValue emitAnyExprToTemp(const clang::Expr *e)
Similarly to emitAnyExpr(), however, the result will always be accessible even if no aggregate locati...
void finishFunction(SourceLocation endLoc)
mlir::LogicalResult emitOMPMaskedTaskLoopSimdDirective(const OMPMaskedTaskLoopSimdDirective &s)
mlir::LogicalResult emitOMPAtomicDirective(const OMPAtomicDirective &s)
mlir::LogicalResult emitOpenACCShutdownConstruct(const OpenACCShutdownConstruct &s)
mlir::LogicalResult emitFunctionBody(const clang::Stmt *body)
mlir::LogicalResult emitBreakStmt(const clang::BreakStmt &s)
void initFullExprCleanupWithFlag(Address activeFlag)
cir::CoroDestroyOp emitCoroDestroyBuiltinCall(const CallExpr *e)
mlir::LogicalResult emitIndirectGotoStmt(const IndirectGotoStmt &s)
mlir::LogicalResult emitOMPTeamsDistributeParallelForSimdDirective(const OMPTeamsDistributeParallelForSimdDirective &s)
mlir::LogicalResult emitOMPTaskgroupDirective(const OMPTaskgroupDirective &s)
mlir::Value emitTernaryOnBoolExpr(const clang::Expr *cond, mlir::Location loc, const clang::Stmt *thenS, const clang::Stmt *elseS)
void 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
mlir::LogicalResult emitOMPParallelMaskedTaskLoopSimdDirective(const OMPParallelMaskedTaskLoopSimdDirective &s)
mlir::LogicalResult emitOMPTeamsDistributeDirective(const OMPTeamsDistributeDirective &s)
LValue emitUnaryOpLValue(const clang::UnaryOperator *e)
void emitReturnOfRValue(mlir::Location loc, RValue rv, QualType ty)
Address createCleanupActiveFlag()
Create an active flag variable for use with conditional cleanups.
bool shouldEmitVTableTypeCheckedLoad(const CXXRecordDecl *rd)
Returns whether we should perform a type checked load when loading a virtual function for virtual cal...
bool hasVolatileMember(QualType t)
returns true if aggregate type has a volatile member.
RValue emitLoadOfBitfieldLValue(LValue lv, SourceLocation loc)
mlir::LogicalResult emitOMPInteropDirective(const OMPInteropDirective &s)
mlir::LogicalResult emitOMPErrorDirective(const OMPErrorDirective &s)
LValue emitComplexAssignmentLValue(const BinaryOperator *e)
mlir::LogicalResult emitOMPSingleDirective(const OMPSingleDirective &s)
void emitCallArg(CallArgList &args, const clang::Expr *e, clang::QualType argType)
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.
mlir::LogicalResult emitOMPTaskyieldDirective(const OMPTaskyieldDirective &s)
void emitConstructorBody(FunctionArgList &args)
LValue emitLValueForFieldInitialization(LValue base, const clang::FieldDecl *field, llvm::StringRef fieldName)
Like emitLValueForField, excpet that if the Field is a reference, this will return the address of the...
mlir::Value getAsNaturalPointerTo(Address addr, QualType pointeeType)
mlir::LogicalResult emitOMPTargetTeamsDistributeSimdDirective(const OMPTargetTeamsDistributeSimdDirective &s)
LValue emitCallExprLValue(const clang::CallExpr *e)
mlir::LogicalResult emitOMPScanDirective(const OMPScanDirective &s)
bool haveInsertPoint() const
True if an insertion point is defined.
llvm::SmallVector< mlir::Type, 2 > condTypeStack
The type of the condition for the emitting switch statement.
RValue emitBuiltinWithOneOverloadedType(const CallExpr *e, llvm::StringRef intrinName, mlir::Type resultType={})
Emit a simple LLVM intrinsic that takes N scalar arguments.
mlir::LogicalResult emitOMPTargetEnterDataDirective(const OMPTargetEnterDataDirective &s)
void emitAutoVarInit(const AutoVarEmission &emission)
Emit the initializer for an allocated variable.
void emitInitializerForField(clang::FieldDecl *field, LValue lhs, clang::Expr *init)
void emitStopPoint(const Stmt *s)
Build a debug stoppoint if we are emitting debug info.
std::optional< mlir::Value > emitAMDGPUBuiltinExpr(unsigned builtinID, const CallExpr *expr)
Emit a call to an AMDGPU builtin function.
std::optional< mlir::Value > emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, ReturnValueSlot returnValue, llvm::Triple::ArchType arch)
void emitCXXTemporary(const CXXTemporary *temporary, QualType tempType, Address ptr)
Emits all the code to cause the given temporary to be cleaned up.
LValue emitStringLiteralLValue(const StringLiteral *e, llvm::StringRef name=".str")
mlir::LogicalResult emitOMPMasterTaskLoopDirective(const OMPMasterTaskLoopDirective &s)
void emitAtomicExprWithMemOrder(const Expr *memOrder, bool isStore, bool isLoad, bool isFence, llvm::function_ref< void(cir::MemOrder)> emitAtomicOp)
void maybeEmitDeferredVarDeclInit(const VarDecl *vd)
mlir::Value getUndefConstant(mlir::Location loc, mlir::Type cirTy)
Return a CIR constant for an undefined value of cirTy.
llvm::SmallDenseMap< const ParmVarDecl *, const ImplicitParamDecl * > sizeArguments
If a ParmVarDecl had the pass_object_size attribute, this will contain a mapping from said ParmVarDec...
void emitVAEnd(mlir::Value vaList)
Emits the end of a CIR variable-argument operation (cir.va_start)
mlir::Value emitToMemory(mlir::Value value, clang::QualType ty)
Given a value and its clang type, returns the value casted to its memory representation.
mlir::LogicalResult emitOpenACCHostDataConstruct(const OpenACCHostDataConstruct &s)
std::optional< mlir::Value > emitAArch64SMEBuiltinExpr(unsigned builtinID, const CallExpr *expr)
LValue emitLValueForField(LValue base, const clang::FieldDecl *field)
mlir::Value emitScalarExpr(const clang::Expr *e, bool ignoreResultAssign=false)
Emit the computation of the specified expression of scalar type.
void pushStackRestore(CleanupKind kind, Address spMem)
LValue emitPseudoObjectLValue(const PseudoObjectExpr *E)
mlir::LogicalResult emitIfStmt(const clang::IfStmt &s)
mlir::LogicalResult emitOMPForDirective(const OMPForDirective &s)
void emitAutoVarDecl(const clang::VarDecl &d)
Emit code and set up symbol table for a variable declaration with auto, register, or no storage class...
cir::GetGlobalOp createGetCpuModel(mlir::Location loc)
mlir::LogicalResult emitOMPMasterDirective(const OMPMasterDirective &s)
void popCleanupBlocks(EHScopeStack::stable_iterator oldCleanupStackDepth, ArrayRef< mlir::Value * > valuesToReload={})
Takes the old cleanup stack size and emits the cleanup blocks that have been added.
mlir::Value emitPromotedScalarExpr(const Expr *e, QualType promotionType)
AggValueSlot::Overlap_t getOverlapForReturnValue()
Determine whether a return value slot may overlap some other object.
bool needsEHCleanup(QualType::DestructionKind kind)
Determines whether an EH cleanup is required to destroy a type with the given destruction kind.
mlir::LogicalResult emitSwitchCase(const clang::SwitchCase &s, bool buildingTopLevelCase)
Address emitLoadOfReference(LValue refLVal, mlir::Location loc, LValueBaseInfo *pointeeBaseInfo)
Address getAddressOfDirectBaseInCompleteClass(mlir::Location loc, Address value, const CXXRecordDecl *derived, const CXXRecordDecl *base, bool baseIsVirtual)
Convert the given pointer to a complete class to the given direct base.
bool shouldNullCheckClassCastValue(const CastExpr *ce)
mlir::LogicalResult emitOMPMetaDirective(const OMPMetaDirective &s)
mlir::LogicalResult emitOMPDistributeSimdDirective(const OMPDistributeSimdDirective &s)
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)
bool didCallStackSave
Whether a cir.stacksave operation has been added.
void emitDecl(const clang::Decl &d, bool evaluateConditionDecl=false)
mlir::LogicalResult emitOMPParallelGenericLoopDirective(const OMPParallelGenericLoopDirective &s)
LValue emitBinaryOperatorLValue(const BinaryOperator *e)
mlir::Value emitOpenACCIntExpr(const Expr *intExpr)
mlir::LogicalResult emitOMPMaskedDirective(const OMPMaskedDirective &s)
Address getAddrOfBitFieldStorage(LValue base, const clang::FieldDecl *field, mlir::Type fieldType, unsigned index)
AggValueSlot::Overlap_t getOverlapForBaseInit(const CXXRecordDecl *rd, const CXXRecordDecl *baseRD, bool isVirtual)
Determine whether a base class initialization may overlap some other object.
void emitDestroy(Address addr, QualType type, Destroyer *destroyer)
Immediately perform the destruction of the given object.
void emitNonNullArgCheck(RValue rv, QualType argType, SourceLocation argLoc, AbstractCallee ac, unsigned paramNum)
Create a check for a function parameter that may potentially be declared as non-null.
void pushPendingCleanupToEHStack(const PendingCleanupEntry &entry)
Promote a single pending cleanup entry onto the EH scope stack.
mlir::LogicalResult emitOMPSplitDirective(const OMPSplitDirective &s)
const CIRGenModule & getCIRGenModule() const
void startFunction(clang::GlobalDecl gd, clang::QualType returnType, cir::FuncOp fn, cir::FuncType funcType, FunctionArgList args, clang::SourceLocation loc, clang::SourceLocation startLoc)
Emit code for the start of a function.
llvm::DenseMap< const VarDecl *, mlir::Value > nrvoFlags
A mapping from NRVO variables to the flags used to indicate when the NRVO has been applied to this va...
unsigned counterRefTmp
Hold counters for incrementally naming temporaries.
mlir::MLIRContext & getMLIRContext()
mlir::LogicalResult emitOpenACCEnterDataConstruct(const OpenACCEnterDataConstruct &s)
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::LogicalResult emitOMPTargetExitDataDirective(const OMPTargetExitDataDirective &s)
mlir::Value emitLoadOfScalar(LValue lvalue, SourceLocation loc)
EmitLoadOfScalar - Load a scalar value from an address, taking care to appropriately convert from the...
mlir::Value emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv)
bool containsLabel(const clang::Stmt *s, bool ignoreCaseStmts=false)
Return true if the statement contains a label in it.
mlir::LogicalResult emitOMPOrderedBlockAssocDirective(const OMPOrderedBlockAssocDirective &s)
DeclMapTy localDeclMap
This keeps track of the CIR allocas or globals for local C declarations.
mlir::Value createOpenACCConstantInt(mlir::Location loc, unsigned width, int64_t value)
RValue emitPseudoObjectRValue(const PseudoObjectExpr *e, AggValueSlot slot=AggValueSlot::ignored())
LValue emitDeclRefLValue(const clang::DeclRefExpr *e)
mlir::LogicalResult emitOMPTargetTeamsDistributeParallelForDirective(const OMPTargetTeamsDistributeParallelForDirective &s)
void emitComplexExprIntoLValue(const Expr *e, LValue dest, bool isInit)
void pushEHDestroyIfNeeded(QualType::DestructionKind dtorKind, Address addr, QualType type)
pushEHDestroyIfNeeded - Push the standard destructor for the given type as an EH-only cleanup.
void emitOMPThreadPrivateDecl(const OMPThreadPrivateDecl &d)
std::optional< mlir::Value > emitNVPTXBuiltinExpr(unsigned builtinID, const CallExpr *expr)
Emit a call to an NVPTX builtin function.
void emitOMPGroupPrivateDecl(const OMPGroupPrivateDecl &d)
static void eraseEmptyAndUnusedBlocks(cir::FuncOp func)
Remove leftover empty and unreachable blocks from an emitted function.
llvm::DenseMap< const clang::ValueDecl *, clang::FieldDecl * > lambdaCaptureFields
mlir::LogicalResult emitOMPParallelForDirective(const OMPParallelForDirective &s)
RValue emitCoawaitExpr(const CoawaitExpr &e, AggValueSlot aggSlot=AggValueSlot::ignored(), bool ignoreResult=false)
ConstantEmission tryEmitAsConstant(const DeclRefExpr *refExpr)
Try to emit a reference to the given value without producing it as an l-value.
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)
mlir::LogicalResult emitOMPSectionsDirective(const OMPSectionsDirective &s)
LValue makeAddrLValue(Address addr, QualType ty, AlignmentSource source=AlignmentSource::Type)
int64_t getAccessedFieldNo(unsigned idx, mlir::ArrayAttr elts)
LValue emitPredefinedLValue(const PredefinedExpr *e)
mlir::LogicalResult emitOMPDistributeDirective(const OMPDistributeDirective &s)
RValue emitAnyExpr(const clang::Expr *e, AggValueSlot aggSlot=AggValueSlot::ignored(), bool ignoreResult=false)
Emit code to compute the specified expression which can have any type.
mlir::LogicalResult emitOMPTargetTeamsDistributeParallelForSimdDirective(const OMPTargetTeamsDistributeParallelForSimdDirective &s)
void emitCXXDestructorCall(const CXXDestructorDecl *dd, CXXDtorType type, bool forVirtualBase, bool delegating, Address thisAddr, QualType thisTy)
mlir::LogicalResult emitOMPTargetTeamsGenericLoopDirective(const OMPTargetTeamsGenericLoopDirective &s)
llvm::SmallVector< VPtr, 4 > VPtrsVector
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.
mlir::LogicalResult emitDeclStmt(const clang::DeclStmt &s)
cir::GetGlobalOp createGetCpuFeatures2(mlir::Location loc)
mlir::LogicalResult emitOMPTeamsDistributeSimdDirective(const OMPTeamsDistributeSimdDirective &s)
llvm::DenseMap< const OpaqueValueExpr *, RValue > opaqueRValues
RValue emitNewOrDeleteBuiltinCall(const FunctionProtoType *type, const CallExpr *callExpr, OverloadedOperatorKind op)
mlir::LogicalResult emitDefaultStmt(const clang::DefaultStmt &s, mlir::Type condType, bool buildingTopLevelCase)
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.
mlir::LogicalResult emitOMPTaskLoopSimdDirective(const OMPTaskLoopSimdDirective &s)
void emitAtomicStore(RValue rvalue, LValue dest, bool isInit)
mlir::Value emitStoreThroughBitfieldLValue(RValue src, LValue dstresult)
llvm::DenseMap< const OpaqueValueExpr *, LValue > opaqueLValues
Keeps track of the current set of opaque value expressions.
const CIRGenFunctionInfo * curFnInfo
CIRGenFunction(CIRGenModule &cgm, CIRGenBuilderTy &builder, bool suppressNewContext=false)
cir::CoroIdOp emitCoroIDBuiltinCall(const CallExpr *e)
void terminateStructuredRegionBody(mlir::Region &r, mlir::Location loc)
Address createMemTempWithoutCast(QualType t, mlir::Location loc, const Twine &name="tmp")
LValue emitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *e)
LValue emitExtVectorElementExpr(const ExtVectorElementExpr *e)
clang::ASTContext & getContext() const
RValue emitCXXMemberOrOperatorMemberCallExpr(const clang::CallExpr *ce, const clang::CXXMethodDecl *md, ReturnValueSlot returnValue, bool hasQualifier, clang::NestedNameSpecifier qualifier, bool isArrow, const clang::Expr *base)
void setAddrOfLocalVar(const clang::VarDecl *vd, Address addr)
Set the address of a local variable.
mlir::Value emitScalarConstant(const ConstantEmission &constant, Expr *e)
RValue emitBuiltinExpr(const clang::GlobalDecl &gd, unsigned builtinID, const clang::CallExpr *e, ReturnValueSlot returnValue)
void emitSYCLKernelCaller(const clang::OutlinedFunctionDecl *outlinedFnDecl, cir::FuncOp funcOp, cir::FuncType funcType, FunctionArgList &args)
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 emitOMPCapturedExpr(const OMPCapturedExprDecl &d)
void emitStoreThroughLValue(RValue src, LValue dst, bool isInit=false)
Store the specified rvalue into the specified lvalue, where both are guaranteed to the have the same ...
mlir::LogicalResult emitOMPParallelMasterTaskLoopDirective(const OMPParallelMasterTaskLoopDirective &s)
bool isLValueSuitableForInlineAtomic(LValue lv)
An LValue is a candidate for having its loads and stores be made atomic if we are operating under /vo...
mlir::LogicalResult emitStmt(const clang::Stmt *s, bool useCurrentScope, llvm::ArrayRef< const Attr * > attrs={})
void pushLifetimeExtendedDestroy(CleanupKind kind, Address addr, QualType type, Destroyer *destroyer, bool useEHCleanupForArray)
RValue getOrCreateOpaqueRValueMapping(const OpaqueValueExpr *e)
Given an opaque value expression, return its RValue mapping if it exists, otherwise create one.
mlir::LogicalResult emitOMPCancelDirective(const OMPCancelDirective &s)
Address createTempAllocaWithoutCast(mlir::Type ty, CharUnits align, mlir::Location loc, const Twine &name="tmp", mlir::Value arraySize=nullptr, mlir::OpBuilder::InsertPoint ip={})
This creates a alloca and inserts it into the entry block of the current region.
mlir::Value emitFromMemory(mlir::Value value, clang::QualType ty)
EmitFromMemory - Change a scalar value from its memory representation to its value representation.
Address emitVAListRef(const Expr *e)
Build a "reference" to a va_list; this is either the address or the value of the expression,...
mlir::LogicalResult emitOMPStripeDirective(const OMPStripeDirective &s)
mlir::LogicalResult emitOMPTargetTeamsDistributeDirective(const OMPTargetTeamsDistributeDirective &s)
mlir::LogicalResult emitCompoundStmtWithoutScope(const clang::CompoundStmt &s, Address *lastValue=nullptr, AggValueSlot slot=AggValueSlot::ignored())
mlir::LogicalResult emitOMPParallelSectionsDirective(const OMPParallelSectionsDirective &s)
mlir::LogicalResult emitOpenACCExitDataConstruct(const OpenACCExitDataConstruct &s)
void 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)
ConditionalInfo emitConditionalBlocks(const AbstractConditionalOperator *e, const FuncTy &branchGenFunc)
Address createDefaultAlignTempAlloca(mlir::Type ty, mlir::Location loc, const Twine &name)
CreateDefaultAlignTempAlloca - This creates an alloca with the default alignment of the corresponding...
mlir::Value emitAlloca(llvm::StringRef name, mlir::Type ty, mlir::Location loc, clang::CharUnits alignment, mlir::OpBuilder::InsertPoint ip, mlir::Value arraySize=nullptr)
mlir::LogicalResult emitOpenACCAtomicConstruct(const OpenACCAtomicConstruct &s)
mlir::LogicalResult emitOMPTargetSimdDirective(const OMPTargetSimdDirective &s)
LValue emitCXXConstructLValue(const CXXConstructExpr *e)
void finishThunk()
Finish generating a thunk function.
mlir::LogicalResult emitOMPAssumeDirective(const OMPAssumeDirective &s)
mlir::Value emitVAArg(VAArgExpr *ve)
Generate code to get an argument from the passed in pointer and update it accordingly.
RValue emitCXXPseudoDestructorExpr(const CXXPseudoDestructorExpr *expr)
LValue emitCompoundLiteralLValue(const CompoundLiteralExpr *e)
void emitAutoVarCleanups(const AutoVarEmission &emission)
RValue emitRotate(const CallExpr *e, bool isRotateLeft)
mlir::LogicalResult emitOpenACCLoopConstruct(const OpenACCLoopConstruct &s)
CIRGenCallee emitCallee(const clang::Expr *e)
Address emitAddrOfFieldStorage(Address base, const FieldDecl *field, llvm::StringRef fieldName, unsigned fieldIndex)
This class organizes the cross-function state that is used while generating CIR code.
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
This class organizes the cross-module state that is used while lowering AST types to CIR types.
Definition CIRGenTypes.h: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:2641
Represents a C++ base or member initializer.
Definition DeclCXX.h:2406
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:2906
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:2149
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:5385
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:3731
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:8458
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:4044
static bool shouldEmitLifetimeMarkers(const CodeGenOptions &cgOpts, const LangOptions &langOpts)
shouldEmitLifetimeMarkers - Decide whether we need emit the life-time markers.
AlignmentSource
The source of the alignment of an l-value; an expression of confidence in the alignment actually matc...
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
@ NormalCleanup
Denotes a cleanup that should run when a scope is exited using normal control flow (falling off the e...
const internal::VariadicDynCastAllOfMatcher< Decl, VarDecl > varDecl
Matches variable declarations.
const internal::VariadicDynCastAllOfMatcher< Stmt, CallExpr > callExpr
Matches call expressions.
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const AstTypeMatcher< ArrayType > arrayType
const internal::VariadicAllOfMatcher< Stmt > stmt
Matches statements.
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
@ Address
A pointer to a ValueDecl.
Definition Primitives.h:28
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
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.
A cleanup that was pushed to the EH stack but whose deactivation is deferred until the enclosing Clea...
Represents a scope, including function bodies, compound statements, and the substatements of if/while...
llvm::ArrayRef< mlir::Block * > getRetBlocks()
mlir::Block * getOrCreateRetBlock(CIRGenFunction &cgf, mlir::Location loc)
LexicalScope(CIRGenFunction &cgf, mlir::Location loc, mlir::Block *eb)
void updateRetLoc(mlir::Block *b, mlir::Location loc)
mlir::Location getRetLoc(mlir::Block *b)
A cleanup entry that will be promoted onto the EH scope stack at a later point.
llvm::PointerUnion< const clang::FunctionProtoType *, const clang::ObjCMethodDecl * > p
PrototypeWrapper(const clang::ObjCMethodDecl *md)
PrototypeWrapper(const clang::FunctionProtoType *ft)
const clang::CXXRecordDecl * vtableClass
const clang::CXXRecordDecl * nearestVBase
VlaSizePair(mlir::Value num, QualType ty)
virtual mlir::LogicalResult operator()(CIRGenFunction &cgf)=0
The this pointer adjustment as well as an optional return adjustment for a thunk.
Definition Thunk.h:157