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