clang 22.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"
36#include "llvm/ADT/ScopedHashTable.h"
37
38namespace {
39class ScalarExprEmitter;
40} // namespace
41
42namespace mlir {
43namespace acc {
44class LoopOp;
45} // namespace acc
46} // namespace mlir
47
48namespace clang::CIRGen {
49
50struct CGCoroData;
51
53public:
55
56private:
57 friend class ::ScalarExprEmitter;
58 /// The builder is a helper class to create IR inside a function. The
59 /// builder is stateful, in particular it keeps an "insertion point": this
60 /// is where the next operations will be introduced.
61 CIRGenBuilderTy &builder;
62
63 /// A jump destination is an abstract label, branching to which may
64 /// require a jump out through normal cleanups.
65 struct JumpDest {
66 JumpDest() = default;
67 JumpDest(mlir::Block *block, EHScopeStack::stable_iterator depth = {},
68 unsigned index = 0)
69 : block(block) {}
70
71 bool isValid() const { return block != nullptr; }
72 mlir::Block *getBlock() const { return block; }
73 EHScopeStack::stable_iterator getScopeDepth() const { return scopeDepth; }
74 unsigned getDestIndex() const { return index; }
75
76 // This should be used cautiously.
77 void setScopeDepth(EHScopeStack::stable_iterator depth) {
78 scopeDepth = depth;
79 }
80
81 private:
82 mlir::Block *block = nullptr;
84 unsigned index;
85 };
86
87public:
88 /// The GlobalDecl for the current function being compiled or the global
89 /// variable currently being initialized.
91
92 /// Unified return block.
93 /// In CIR this is a function because each scope might have
94 /// its associated return block.
95 JumpDest returnBlock(mlir::Block *retBlock) {
96 return getJumpDestInCurrentScope(retBlock);
97 }
98
100
101 /// The compiler-generated variable that holds the return value.
102 std::optional<mlir::Value> fnRetAlloca;
103
104 // Holds coroutine data if the current function is a coroutine. We use a
105 // wrapper to manage its lifetime, so that we don't have to define CGCoroData
106 // in this header.
107 struct CGCoroInfo {
108 std::unique_ptr<CGCoroData> data;
109 CGCoroInfo();
110 ~CGCoroInfo();
111 };
113
114 bool isCoroutine() const { return curCoro.data != nullptr; }
115
116 /// The temporary alloca to hold the return value. This is
117 /// invalid iff the function has no return value.
119
120 /// Tracks function scope overall cleanup handling.
122
124
125 llvm::DenseMap<const clang::ValueDecl *, clang::FieldDecl *>
128
129 /// CXXThisDecl - When generating code for a C++ member function,
130 /// this will hold the implicit 'this' declaration.
132 mlir::Value cxxabiThisValue = nullptr;
133 mlir::Value cxxThisValue = nullptr;
135
136 /// When generating code for a constructor or destructor, this will hold the
137 /// implicit argument (e.g. VTT).
140
141 /// The value of 'this' to sue when evaluating CXXDefaultInitExprs within this
142 /// expression.
144
145 // Holds the Decl for the current outermost non-closure context
146 const clang::Decl *curFuncDecl = nullptr;
147 /// This is the inner-most code context, which includes blocks.
148 const clang::Decl *curCodeDecl = nullptr;
149
150 /// The current function or global initializer that is generated code for.
151 /// This is usually a cir::FuncOp, but it can also be a cir::GlobalOp for
152 /// global initializers.
153 mlir::Operation *curFn = nullptr;
154
155 /// Save Parameter Decl for coroutine.
157
158 using DeclMapTy = llvm::DenseMap<const clang::Decl *, Address>;
159 /// This keeps track of the CIR allocas or globals for local C
160 /// declarations.
162
163 /// The type of the condition for the emitting switch statement.
165
166 clang::ASTContext &getContext() const { return cgm.getASTContext(); }
167
168 CIRGenBuilderTy &getBuilder() { return builder; }
169
171 const CIRGenModule &getCIRGenModule() const { return cgm; }
172
174 // We currently assume this isn't called for a global initializer.
175 auto fn = mlir::cast<cir::FuncOp>(curFn);
176 return &fn.getRegion().front();
177 }
178
179 /// Sanitizers enabled for this function.
181
182 /// The symbol table maps a variable name to a value in the current scope.
183 /// Entering a function creates a new scope, and the function arguments are
184 /// added to the mapping. When the processing of a function is terminated,
185 /// the scope is destroyed and the mappings created in this scope are
186 /// dropped.
187 using SymTableTy = llvm::ScopedHashTable<const clang::Decl *, mlir::Value>;
189
190 /// Whether a cir.stacksave operation has been added. Used to avoid
191 /// inserting cir.stacksave for multiple VLAs in the same scope.
192 bool didCallStackSave = false;
193
194 /// Whether or not a Microsoft-style asm block has been processed within
195 /// this fuction. These can potentially set the return value.
196 bool sawAsmBlock = false;
197
198 mlir::Type convertTypeForMem(QualType t);
199
200 mlir::Type convertType(clang::QualType t);
201 mlir::Type convertType(const TypeDecl *t) {
202 return convertType(getContext().getTypeDeclType(t));
203 }
204
205 /// Return the cir::TypeEvaluationKind of QualType \c type.
207
211
215
217 bool suppressNewContext = false);
219
220 CIRGenTypes &getTypes() const { return cgm.getTypes(); }
221
222 const TargetInfo &getTarget() const { return cgm.getTarget(); }
223 mlir::MLIRContext &getMLIRContext() { return cgm.getMLIRContext(); }
224
226 return cgm.getTargetCIRGenInfo();
227 }
228
229 // ---------------------
230 // Opaque value handling
231 // ---------------------
232
233 /// Keeps track of the current set of opaque value expressions.
234 llvm::DenseMap<const OpaqueValueExpr *, LValue> opaqueLValues;
235 llvm::DenseMap<const OpaqueValueExpr *, RValue> opaqueRValues;
236
237 // This keeps track of the associated size for each VLA type.
238 // We track this by the size expression rather than the type itself because
239 // in certain situations, like a const qualifier applied to an VLA typedef,
240 // multiple VLA types can share the same size expression.
241 // FIXME: Maybe this could be a stack of maps that is pushed/popped as we
242 // enter/leave scopes.
243 llvm::DenseMap<const Expr *, mlir::Value> vlaSizeMap;
244
245public:
246 /// A non-RAII class containing all the information about a bound
247 /// opaque value. OpaqueValueMapping, below, is a RAII wrapper for
248 /// this which makes individual mappings very simple; using this
249 /// class directly is useful when you have a variable number of
250 /// opaque values or don't want the RAII functionality for some
251 /// reason.
252 class OpaqueValueMappingData {
253 const OpaqueValueExpr *opaqueValue;
254 bool boundLValue;
255
256 OpaqueValueMappingData(const OpaqueValueExpr *ov, bool boundLValue)
257 : opaqueValue(ov), boundLValue(boundLValue) {}
258
259 public:
260 OpaqueValueMappingData() : opaqueValue(nullptr) {}
261
262 static bool shouldBindAsLValue(const Expr *expr) {
263 // gl-values should be bound as l-values for obvious reasons.
264 // Records should be bound as l-values because IR generation
265 // always keeps them in memory. Expressions of function type
266 // act exactly like l-values but are formally required to be
267 // r-values in C.
268 return expr->isGLValue() || expr->getType()->isFunctionType() ||
270 }
271
273 bind(CIRGenFunction &cgf, const OpaqueValueExpr *ov, const Expr *e) {
274 if (shouldBindAsLValue(ov))
275 return bind(cgf, ov, cgf.emitLValue(e));
276 return bind(cgf, ov, cgf.emitAnyExpr(e));
277 }
278
280 bind(CIRGenFunction &cgf, const OpaqueValueExpr *ov, const LValue &lv) {
281 assert(shouldBindAsLValue(ov));
282 cgf.opaqueLValues.insert(std::make_pair(ov, lv));
283 return OpaqueValueMappingData(ov, true);
284 }
285
287 bind(CIRGenFunction &cgf, const OpaqueValueExpr *ov, const RValue &rv) {
288 assert(!shouldBindAsLValue(ov));
289 cgf.opaqueRValues.insert(std::make_pair(ov, rv));
290
291 OpaqueValueMappingData data(ov, false);
292
293 // Work around an extremely aggressive peephole optimization in
294 // EmitScalarConversion which assumes that all other uses of a
295 // value are extant.
297 return data;
298 }
299
300 bool isValid() const { return opaqueValue != nullptr; }
301 void clear() { opaqueValue = nullptr; }
302
304 assert(opaqueValue && "no data to unbind!");
305
306 if (boundLValue) {
307 cgf.opaqueLValues.erase(opaqueValue);
308 } else {
309 cgf.opaqueRValues.erase(opaqueValue);
311 }
312 }
313 };
314
315 /// An RAII object to set (and then clear) a mapping for an OpaqueValueExpr.
317 CIRGenFunction &cgf;
319
320 public:
324
325 /// Build the opaque value mapping for the given conditional
326 /// operator if it's the GNU ?: extension. This is a common
327 /// enough pattern that the convenience operator is really
328 /// helpful.
329 ///
332 : cgf(cgf) {
333 if (mlir::isa<ConditionalOperator>(op))
334 // Leave Data empty.
335 return;
336
338 mlir::cast<BinaryConditionalOperator>(op);
340 e->getCommon());
341 }
342
343 /// Build the opaque value mapping for an OpaqueValueExpr whose source
344 /// expression is set to the expression the OVE represents.
346 : cgf(cgf) {
347 if (ov) {
348 assert(ov->getSourceExpr() && "wrong form of OpaqueValueMapping used "
349 "for OVE with no source expression");
350 data = OpaqueValueMappingData::bind(cgf, ov, ov->getSourceExpr());
351 }
352 }
353
355 LValue lvalue)
356 : cgf(cgf),
357 data(OpaqueValueMappingData::bind(cgf, opaqueValue, lvalue)) {}
358
360 RValue rvalue)
361 : cgf(cgf),
362 data(OpaqueValueMappingData::bind(cgf, opaqueValue, rvalue)) {}
363
364 void pop() {
365 data.unbind(cgf);
366 data.clear();
367 }
368
370 if (data.isValid())
371 data.unbind(cgf);
372 }
373 };
374
375private:
376 /// Declare a variable in the current scope, return success if the variable
377 /// wasn't declared yet.
378 void declare(mlir::Value addrVal, const clang::Decl *var, clang::QualType ty,
379 mlir::Location loc, clang::CharUnits alignment,
380 bool isParam = false);
381
382public:
383 mlir::Value createDummyValue(mlir::Location loc, clang::QualType qt);
384
385 void emitNullInitialization(mlir::Location loc, Address destPtr, QualType ty);
386
387private:
388 // Track current variable initialization (if there's one)
389 const clang::VarDecl *currVarDecl = nullptr;
390 class VarDeclContext {
392 const clang::VarDecl *oldVal = nullptr;
393
394 public:
395 VarDeclContext(CIRGenFunction &p, const VarDecl *value) : p(p) {
396 if (p.currVarDecl)
397 oldVal = p.currVarDecl;
398 p.currVarDecl = value;
399 }
400
401 /// Can be used to restore the state early, before the dtor
402 /// is run.
403 void restore() { p.currVarDecl = oldVal; }
404 ~VarDeclContext() { restore(); }
405 };
406
407public:
408 /// Use to track source locations across nested visitor traversals.
409 /// Always use a `SourceLocRAIIObject` to change currSrcLoc.
410 std::optional<mlir::Location> currSrcLoc;
412 CIRGenFunction &cgf;
413 std::optional<mlir::Location> oldLoc;
414
415 public:
416 SourceLocRAIIObject(CIRGenFunction &cgf, mlir::Location value) : cgf(cgf) {
417 if (cgf.currSrcLoc)
418 oldLoc = cgf.currSrcLoc;
419 cgf.currSrcLoc = value;
420 }
421
422 /// Can be used to restore the state early, before the dtor
423 /// is run.
424 void restore() { cgf.currSrcLoc = oldLoc; }
426 };
427
429 llvm::ScopedHashTableScope<const clang::Decl *, mlir::Value>;
430
431 /// Hold counters for incrementally naming temporaries
432 unsigned counterRefTmp = 0;
433 unsigned counterAggTmp = 0;
434 std::string getCounterRefTmpAsString();
435 std::string getCounterAggTmpAsString();
436
437 /// Helpers to convert Clang's SourceLocation to a MLIR Location.
438 mlir::Location getLoc(clang::SourceLocation srcLoc);
439 mlir::Location getLoc(clang::SourceRange srcLoc);
440 mlir::Location getLoc(mlir::Location lhs, mlir::Location rhs);
441
442 const clang::LangOptions &getLangOpts() const { return cgm.getLangOpts(); }
443
444 /// True if an insertion point is defined. If not, this indicates that the
445 /// current code being emitted is unreachable.
446 /// FIXME(cir): we need to inspect this and perhaps use a cleaner mechanism
447 /// since we don't yet force null insertion point to designate behavior (like
448 /// LLVM's codegen does) and we probably shouldn't.
449 bool haveInsertPoint() const {
450 return builder.getInsertionBlock() != nullptr;
451 }
452
453 // Wrapper for function prototype sources. Wraps either a FunctionProtoType or
454 // an ObjCMethodDecl.
456 llvm::PointerUnion<const clang::FunctionProtoType *,
457 const clang::ObjCMethodDecl *>
459
462 };
463
465
466 /// An abstract representation of regular/ObjC call/message targets.
468 /// The function declaration of the callee.
469 [[maybe_unused]] const clang::Decl *calleeDecl;
470
471 public:
472 AbstractCallee() : calleeDecl(nullptr) {}
473 AbstractCallee(const clang::FunctionDecl *fd) : calleeDecl(fd) {}
474
475 bool hasFunctionDecl() const {
476 return llvm::isa_and_nonnull<clang::FunctionDecl>(calleeDecl);
477 }
478
479 unsigned getNumParams() const {
480 if (const auto *fd = llvm::dyn_cast<clang::FunctionDecl>(calleeDecl))
481 return fd->getNumParams();
482 return llvm::cast<clang::ObjCMethodDecl>(calleeDecl)->param_size();
483 }
484
485 const clang::ParmVarDecl *getParamDecl(unsigned I) const {
486 if (const auto *fd = llvm::dyn_cast<clang::FunctionDecl>(calleeDecl))
487 return fd->getParamDecl(I);
488 return *(llvm::cast<clang::ObjCMethodDecl>(calleeDecl)->param_begin() +
489 I);
490 }
491 };
492
493 struct VlaSizePair {
494 mlir::Value numElts;
496
497 VlaSizePair(mlir::Value num, QualType ty) : numElts(num), type(ty) {}
498 };
499
500 /// Returns an MLIR::Value+QualType pair that corresponds to the size,
501 /// in non-variably-sized elements, of a variable length array type,
502 /// plus that largest non-variably-sized element type. Assumes that
503 /// the type has already been emitted with emitVariablyModifiedType.
504 VlaSizePair getVLASize(const VariableArrayType *type);
505 VlaSizePair getVLASize(QualType type);
506
508
509 mlir::Value getAsNaturalPointerTo(Address addr, QualType pointeeType) {
510 return getAsNaturalAddressOf(addr, pointeeType).getBasePointer();
511 }
512
513 void finishFunction(SourceLocation endLoc);
514
515 /// Determine whether the given initializer is trivial in the sense
516 /// that it requires no code to be generated.
517 bool isTrivialInitializer(const Expr *init);
518
519 /// If the specified expression does not fold to a constant, or if it does but
520 /// contains a label, return false. If it constant folds return true and set
521 /// the boolean result in Result.
522 bool constantFoldsToBool(const clang::Expr *cond, bool &resultBool,
523 bool allowLabels = false);
525 llvm::APSInt &resultInt,
526 bool allowLabels = false);
527
528 /// Return true if the statement contains a label in it. If
529 /// this statement is not executed normally, it not containing a label means
530 /// that we can just remove the code.
531 bool containsLabel(const clang::Stmt *s, bool ignoreCaseStmts = false);
532
533 class ConstantEmission {
534 // Cannot use mlir::TypedAttr directly here because of bit availability.
535 llvm::PointerIntPair<mlir::Attribute, 1, bool> valueAndIsReference;
536 ConstantEmission(mlir::TypedAttr c, bool isReference)
537 : valueAndIsReference(c, isReference) {}
538
539 public:
541 static ConstantEmission forReference(mlir::TypedAttr c) {
542 return ConstantEmission(c, true);
543 }
544 static ConstantEmission forValue(mlir::TypedAttr c) {
545 return ConstantEmission(c, false);
546 }
547
548 explicit operator bool() const {
549 return valueAndIsReference.getOpaqueValue() != nullptr;
550 }
551
552 bool isReference() const { return valueAndIsReference.getInt(); }
554 assert(isReference());
555 cgf.cgm.errorNYI(refExpr->getSourceRange(),
556 "ConstantEmission::getReferenceLValue");
557 return {};
558 }
559
560 mlir::TypedAttr getValue() const {
561 assert(!isReference());
562 return mlir::cast<mlir::TypedAttr>(valueAndIsReference.getPointer());
563 }
564 };
565
566 ConstantEmission tryEmitAsConstant(const DeclRefExpr *refExpr);
567 ConstantEmission tryEmitAsConstant(const MemberExpr *me);
568
571 /// The address of the alloca for languages with explicit address space
572 /// (e.g. OpenCL) or alloca casted to generic pointer for address space
573 /// agnostic languages (e.g. C++). Invalid if the variable was emitted
574 /// as a global constant.
576
577 /// True if the variable is of aggregate type and has a constant
578 /// initializer.
580
581 /// True if the variable is a __block variable that is captured by an
582 /// escaping block.
583 bool isEscapingByRef = false;
584
585 /// True if the variable was emitted as an offload recipe, and thus doesn't
586 /// have the same sort of alloca initialization.
587 bool emittedAsOffload = false;
588
589 mlir::Value nrvoFlag{};
590
591 struct Invalid {};
593
596
598
599 bool wasEmittedAsGlobal() const { return !addr.isValid(); }
600
602
603 /// Returns the raw, allocated address, which is not necessarily
604 /// the address of the object itself. It is casted to default
605 /// address space for address space agnostic languages.
606 Address getAllocatedAddress() const { return addr; }
607
608 // Changes the stored address for the emission. This function should only
609 // be used in extreme cases, and isn't required to model normal AST
610 // initialization/variables.
612
613 /// Returns the address of the object within this declaration.
614 /// Note that this does not chase the forwarding pointer for
615 /// __block decls.
617 if (!isEscapingByRef)
618 return addr;
619
621 return Address::invalid();
622 }
623 };
624
625 /// The given basic block lies in the current EH scope, but may be a
626 /// target of a potentially scope-crossing jump; get a stable handle
627 /// to which we can perform this jump later.
628 /// CIRGen: this mostly tracks state for figuring out the proper scope
629 /// information, no actual branches are emitted.
630 JumpDest getJumpDestInCurrentScope(mlir::Block *target) {
631 return JumpDest(target, ehStack.getInnermostNormalCleanup(),
633 }
634
635 /// Perform the usual unary conversions on the specified expression and
636 /// compare the result against zero, returning an Int1Ty value.
637 mlir::Value evaluateExprAsBool(const clang::Expr *e);
638
639 cir::GlobalOp addInitializerToStaticVarDecl(const VarDecl &d,
640 cir::GlobalOp gv,
641 cir::GetGlobalOp gvAddr);
642
643 /// Enter the cleanups necessary to complete the given phase of destruction
644 /// for a destructor. The end result should call destructors on members and
645 /// base classes in reverse order of their construction.
647
648 /// Determines whether an EH cleanup is required to destroy a type
649 /// with the given destruction kind.
650 /// TODO(cir): could be shared with Clang LLVM codegen
652 switch (kind) {
654 return false;
658 return getLangOpts().Exceptions;
660 return getLangOpts().Exceptions &&
661 cgm.getCodeGenOpts().ObjCAutoRefCountExceptions;
662 }
663 llvm_unreachable("bad destruction kind");
664 }
665
669
670 void pushStackRestore(CleanupKind kind, Address spMem);
671
672 /// Set the address of a local variable.
674 assert(!localDeclMap.count(vd) && "Decl already exists in LocalDeclMap!");
675 localDeclMap.insert({vd, addr});
676
677 // Add to the symbol table if not there already.
678 if (symbolTable.count(vd))
679 return;
680 symbolTable.insert(vd, addr.getPointer());
681 }
682
683 // Replaces the address of the local variable, if it exists. Else does the
684 // same thing as setAddrOfLocalVar.
686 localDeclMap.insert_or_assign(vd, addr);
687 }
688
689 // A class to allow reverting changes to a var-decl's registration to the
690 // localDeclMap. This is used in cases where things are being inserted into
691 // the variable list but don't follow normal lookup/search rules, like in
692 // OpenACC recipe generation.
694 CIRGenFunction &cgf;
695 const VarDecl *vd;
696 bool shouldDelete = false;
697 Address oldAddr = Address::invalid();
698
699 public:
701 : cgf(cgf), vd(vd) {
702 auto mapItr = cgf.localDeclMap.find(vd);
703
704 if (mapItr != cgf.localDeclMap.end())
705 oldAddr = mapItr->second;
706 else
707 shouldDelete = true;
708 }
709
711 if (shouldDelete)
712 cgf.localDeclMap.erase(vd);
713 else
714 cgf.localDeclMap.insert_or_assign(vd, oldAddr);
715 }
716 };
717
719
722
723 static bool
725
732
735
739 const clang::CXXRecordDecl *nearestVBase,
740 clang::CharUnits offsetFromNearestVBase,
741 bool baseIsNonVirtualPrimaryBase,
742 const clang::CXXRecordDecl *vtableClass,
743 VisitedVirtualBasesSetTy &vbases, VPtrsVector &vptrs);
744 /// Return the Value of the vtable pointer member pointed to by thisAddr.
745 mlir::Value getVTablePtr(mlir::Location loc, Address thisAddr,
746 const clang::CXXRecordDecl *vtableClass);
747
748 /// Returns whether we should perform a type checked load when loading a
749 /// virtual function for virtual calls to members of RD. This is generally
750 /// true when both vcall CFI and whole-program-vtables are enabled.
752
753 /// Source location information about the default argument or member
754 /// initializer expression we're evaluating, if any.
758
759 /// A scope within which we are constructing the fields of an object which
760 /// might use a CXXDefaultInitExpr. This stashes away a 'this' value to use if
761 /// we need to evaluate the CXXDefaultInitExpr within the evaluation.
763 public:
765 : cgf(cgf), oldCXXDefaultInitExprThis(cgf.cxxDefaultInitExprThis) {
766 cgf.cxxDefaultInitExprThis = thisAddr;
767 }
769 cgf.cxxDefaultInitExprThis = oldCXXDefaultInitExprThis;
770 }
771
772 private:
773 CIRGenFunction &cgf;
774 Address oldCXXDefaultInitExprThis;
775 };
776
777 /// The scope of a CXXDefaultInitExpr. Within this scope, the value of 'this'
778 /// is overridden to be the object under construction.
780 public:
785 cgf.cxxThisValue = cgf.cxxDefaultInitExprThis.getPointer();
786 cgf.cxxThisAlignment = cgf.cxxDefaultInitExprThis.getAlignment();
787 }
789 cgf.cxxThisValue = oldCXXThisValue;
790 cgf.cxxThisAlignment = oldCXXThisAlignment;
791 }
792
793 public:
795 mlir::Value oldCXXThisValue;
798 };
799
804
806 LValue makeNaturalAlignAddrLValue(mlir::Value val, QualType ty);
807
808 /// Construct an address with the natural alignment of T. If a pointer to T
809 /// is expected to be signed, the pointer passed to this function must have
810 /// been signed, and the returned Address will have the pointer authentication
811 /// information needed to authenticate the signed pointer.
813 CharUnits alignment,
814 bool forPointeeType = false,
815 LValueBaseInfo *baseInfo = nullptr) {
816 if (alignment.isZero())
817 alignment = cgm.getNaturalTypeAlignment(t, baseInfo);
818 return Address(ptr, convertTypeForMem(t), alignment);
819 }
820
822 Address value, const CXXRecordDecl *derived,
823 llvm::iterator_range<CastExpr::path_const_iterator> path,
824 bool nullCheckValue, SourceLocation loc);
825
827 mlir::Location loc, Address baseAddr, const CXXRecordDecl *derived,
828 llvm::iterator_range<CastExpr::path_const_iterator> path,
829 bool nullCheckValue);
830
831 /// Return the VTT parameter that should be passed to a base
832 /// constructor/destructor with virtual bases.
833 /// FIXME: VTTs are Itanium ABI-specific, so the definition should move
834 /// to ItaniumCXXABI.cpp together with all the references to VTT.
835 mlir::Value getVTTParameter(GlobalDecl gd, bool forVirtualBase,
836 bool delegating);
837
840 return makeAddrLValue(addr, ty, LValueBaseInfo(source));
841 }
842
844 return LValue::makeAddr(addr, ty, baseInfo);
845 }
846
847 void initializeVTablePointers(mlir::Location loc,
848 const clang::CXXRecordDecl *rd);
849 void initializeVTablePointer(mlir::Location loc, const VPtr &vptr);
850
852
853 /// Return the address of a local variable.
855 auto it = localDeclMap.find(vd);
856 assert(it != localDeclMap.end() &&
857 "Invalid argument to getAddrOfLocalVar(), no decl!");
858 return it->second;
859 }
860
862 mlir::Type fieldType, unsigned index);
863
864 /// Given an opaque value expression, return its LValue mapping if it exists,
865 /// otherwise create one.
867
868 /// Given an opaque value expression, return its RValue mapping if it exists,
869 /// otherwise create one.
871
872 /// Load the value for 'this'. This function is only valid while generating
873 /// code for an C++ member function.
874 /// FIXME(cir): this should return a mlir::Value!
875 mlir::Value loadCXXThis() {
876 assert(cxxThisValue && "no 'this' value for this function");
877 return cxxThisValue;
878 }
880
881 /// Load the VTT parameter to base constructors/destructors have virtual
882 /// bases. FIXME: Every place that calls LoadCXXVTT is something that needs to
883 /// be abstracted properly.
884 mlir::Value loadCXXVTT() {
885 assert(cxxStructorImplicitParamValue && "no VTT value for this function");
887 }
888
889 /// Convert the given pointer to a complete class to the given direct base.
891 Address value,
892 const CXXRecordDecl *derived,
893 const CXXRecordDecl *base,
894 bool baseIsVirtual);
895
896 /// Determine whether a return value slot may overlap some other object.
898 // FIXME: Assuming no overlap here breaks guaranteed copy elision for base
899 // class subobjects. These cases may need to be revisited depending on the
900 // resolution of the relevant core issue.
902 }
903
904 /// Determine whether a base class initialization may overlap some other
905 /// object.
907 const CXXRecordDecl *baseRD,
908 bool isVirtual);
909
910 /// Get an appropriate 'undef' rvalue for the given type.
911 /// TODO: What's the equivalent for MLIR? Currently we're only using this for
912 /// void types so it just returns RValue::get(nullptr) but it'll need
913 /// addressed later.
915
916 cir::FuncOp generateCode(clang::GlobalDecl gd, cir::FuncOp fn,
917 cir::FuncType funcType);
918
920 FunctionArgList &args);
921
922 /// Emit code for the start of a function.
923 /// \param loc The location to be associated with the function.
924 /// \param startLoc The location of the function body.
926 cir::FuncOp fn, cir::FuncType funcType,
928 clang::SourceLocation startLoc);
929
930 /// returns true if aggregate type has a volatile member.
932 if (const auto *rd = t->getAsRecordDecl())
933 return rd->hasVolatileMember();
934 return false;
935 }
936
938 cir::TryOp tryOp);
939
940 /// The cleanup depth enclosing all the cleanups associated with the
941 /// parameters.
943
945 void populateCatchHandlersIfRequired(cir::TryOp tryOp);
946
947 /// Takes the old cleanup stack size and emits the cleanup blocks
948 /// that have been added.
949 void popCleanupBlocks(EHScopeStack::stable_iterator oldCleanupStackDepth);
950 void popCleanupBlock();
951
952 /// Push a cleanup to be run at the end of the current full-expression. Safe
953 /// against the possibility that we're currently inside a
954 /// conditionally-evaluated expression.
955 template <class T, class... As>
956 void pushFullExprCleanup(CleanupKind kind, As... a) {
957 // If we're not in a conditional branch, or if none of the
958 // arguments requires saving, then use the unconditional cleanup.
960 return ehStack.pushCleanup<T>(kind, a...);
961
962 cgm.errorNYI("pushFullExprCleanup in conditional branch");
963 }
964
965 /// Enters a new scope for capturing cleanups, all of which
966 /// will be executed once the scope is exited.
967 class RunCleanupsScope {
968 EHScopeStack::stable_iterator cleanupStackDepth, oldCleanupStackDepth;
969
970 protected:
973
974 private:
975 RunCleanupsScope(const RunCleanupsScope &) = delete;
976 void operator=(const RunCleanupsScope &) = delete;
977
978 protected:
980
981 public:
982 /// Enter a new cleanup scope.
985 cleanupStackDepth = cgf.ehStack.stable_begin();
986 oldDidCallStackSave = cgf.didCallStackSave;
987 cgf.didCallStackSave = false;
988 oldCleanupStackDepth = cgf.currentCleanupStackDepth;
989 cgf.currentCleanupStackDepth = cleanupStackDepth;
990 }
991
992 /// Exit this cleanup scope, emitting any accumulated cleanups.
997
998 /// Force the emission of cleanups now, instead of waiting
999 /// until this object is destroyed.
1001 assert(performCleanup && "Already forced cleanup");
1002 {
1003 mlir::OpBuilder::InsertionGuard guard(cgf.getBuilder());
1004 cgf.didCallStackSave = oldDidCallStackSave;
1005 cgf.popCleanupBlocks(cleanupStackDepth);
1006 performCleanup = false;
1007 cgf.currentCleanupStackDepth = oldCleanupStackDepth;
1008 }
1009 }
1010 };
1011
1012 // Cleanup stack depth of the RunCleanupsScope that was pushed most recently.
1014
1015public:
1016 /// Represents a scope, including function bodies, compound statements, and
1017 /// the substatements of if/while/do/for/switch/try statements. This class
1018 /// handles any automatic cleanup, along with the return value.
1019 struct LexicalScope : public RunCleanupsScope {
1020 private:
1021 // Block containing cleanup code for things initialized in this
1022 // lexical context (scope).
1023 mlir::Block *cleanupBlock = nullptr;
1024
1025 // Points to the scope entry block. This is useful, for instance, for
1026 // helping to insert allocas before finalizing any recursive CodeGen from
1027 // switches.
1028 mlir::Block *entryBlock;
1029
1030 LexicalScope *parentScope = nullptr;
1031
1032 // Holds the actual value for ScopeKind::Try
1033 cir::TryOp tryOp = nullptr;
1034
1035 // Only Regular is used at the moment. Support for other kinds will be
1036 // added as the relevant statements/expressions are upstreamed.
1037 enum Kind {
1038 Regular, // cir.if, cir.scope, if_regions
1039 Ternary, // cir.ternary
1040 Switch, // cir.switch
1041 Try, // cir.try
1042 GlobalInit // cir.global initialization code
1043 };
1044 Kind scopeKind = Kind::Regular;
1045
1046 // The scope return value.
1047 mlir::Value retVal = nullptr;
1048
1049 mlir::Location beginLoc;
1050 mlir::Location endLoc;
1051
1052 public:
1053 unsigned depth = 0;
1054
1055 LexicalScope(CIRGenFunction &cgf, mlir::Location loc, mlir::Block *eb)
1056 : RunCleanupsScope(cgf), entryBlock(eb), parentScope(cgf.curLexScope),
1057 beginLoc(loc), endLoc(loc) {
1058
1059 assert(entryBlock && "LexicalScope requires an entry block");
1060 cgf.curLexScope = this;
1061 if (parentScope)
1062 ++depth;
1063
1064 if (const auto fusedLoc = mlir::dyn_cast<mlir::FusedLoc>(loc)) {
1065 assert(fusedLoc.getLocations().size() == 2 && "too many locations");
1066 beginLoc = fusedLoc.getLocations()[0];
1067 endLoc = fusedLoc.getLocations()[1];
1068 }
1069 }
1070
1071 void setRetVal(mlir::Value v) { retVal = v; }
1072
1073 void cleanup();
1074 void restore() { cgf.curLexScope = parentScope; }
1075
1078 cleanup();
1079 restore();
1080 }
1081
1082 // ---
1083 // Kind
1084 // ---
1085 bool isGlobalInit() { return scopeKind == Kind::GlobalInit; }
1086 bool isRegular() { return scopeKind == Kind::Regular; }
1087 bool isSwitch() { return scopeKind == Kind::Switch; }
1088 bool isTernary() { return scopeKind == Kind::Ternary; }
1089 bool isTry() { return scopeKind == Kind::Try; }
1090 cir::TryOp getClosestTryParent();
1091 void setAsGlobalInit() { scopeKind = Kind::GlobalInit; }
1092 void setAsSwitch() { scopeKind = Kind::Switch; }
1093 void setAsTernary() { scopeKind = Kind::Ternary; }
1094 void setAsTry(cir::TryOp op) {
1095 scopeKind = Kind::Try;
1096 tryOp = op;
1097 }
1098
1099 // Lazy create cleanup block or return what's available.
1100 mlir::Block *getOrCreateCleanupBlock(mlir::OpBuilder &builder) {
1101 if (cleanupBlock)
1102 return cleanupBlock;
1103 cleanupBlock = createCleanupBlock(builder);
1104 return cleanupBlock;
1105 }
1106
1107 cir::TryOp getTry() {
1108 assert(isTry());
1109 return tryOp;
1110 }
1111
1112 mlir::Block *getCleanupBlock(mlir::OpBuilder &builder) {
1113 return cleanupBlock;
1114 }
1115
1116 mlir::Block *createCleanupBlock(mlir::OpBuilder &builder) {
1117 // Create the cleanup block but dont hook it up around just yet.
1118 mlir::OpBuilder::InsertionGuard guard(builder);
1119 mlir::Region *r = builder.getBlock() ? builder.getBlock()->getParent()
1120 : &cgf.curFn->getRegion(0);
1121 cleanupBlock = builder.createBlock(r);
1122 return cleanupBlock;
1123 }
1124
1125 // ---
1126 // Return handling.
1127 // ---
1128
1129 private:
1130 // On switches we need one return block per region, since cases don't
1131 // have their own scopes but are distinct regions nonetheless.
1132
1133 // TODO: This implementation should change once we have support for early
1134 // exits in MLIR structured control flow (llvm-project#161575)
1136 llvm::DenseMap<mlir::Block *, mlir::Location> retLocs;
1137 llvm::DenseMap<cir::CaseOp, unsigned> retBlockInCaseIndex;
1138 std::optional<unsigned> normalRetBlockIndex;
1139
1140 // There's usually only one ret block per scope, but this needs to be
1141 // get or create because of potential unreachable return statements, note
1142 // that for those, all source location maps to the first one found.
1143 mlir::Block *createRetBlock(CIRGenFunction &cgf, mlir::Location loc) {
1144 assert((isa_and_nonnull<cir::CaseOp>(
1145 cgf.builder.getBlock()->getParentOp()) ||
1146 retBlocks.size() == 0) &&
1147 "only switches can hold more than one ret block");
1148
1149 // Create the return block but don't hook it up just yet.
1150 mlir::OpBuilder::InsertionGuard guard(cgf.builder);
1151 auto *b = cgf.builder.createBlock(cgf.builder.getBlock()->getParent());
1152 retBlocks.push_back(b);
1153 updateRetLoc(b, loc);
1154 return b;
1155 }
1156
1157 cir::ReturnOp emitReturn(mlir::Location loc);
1158 void emitImplicitReturn();
1159
1160 public:
1162 mlir::Location getRetLoc(mlir::Block *b) { return retLocs.at(b); }
1163 void updateRetLoc(mlir::Block *b, mlir::Location loc) {
1164 retLocs.insert_or_assign(b, loc);
1165 }
1166
1167 mlir::Block *getOrCreateRetBlock(CIRGenFunction &cgf, mlir::Location loc) {
1168 // Check if we're inside a case region
1169 if (auto caseOp = mlir::dyn_cast_if_present<cir::CaseOp>(
1170 cgf.builder.getBlock()->getParentOp())) {
1171 auto iter = retBlockInCaseIndex.find(caseOp);
1172 if (iter != retBlockInCaseIndex.end()) {
1173 // Reuse existing return block
1174 mlir::Block *ret = retBlocks[iter->second];
1175 updateRetLoc(ret, loc);
1176 return ret;
1177 }
1178 // Create new return block
1179 mlir::Block *ret = createRetBlock(cgf, loc);
1180 retBlockInCaseIndex[caseOp] = retBlocks.size() - 1;
1181 return ret;
1182 }
1183
1184 if (normalRetBlockIndex) {
1185 mlir::Block *ret = retBlocks[*normalRetBlockIndex];
1186 updateRetLoc(ret, loc);
1187 return ret;
1188 }
1189
1190 mlir::Block *ret = createRetBlock(cgf, loc);
1191 normalRetBlockIndex = retBlocks.size() - 1;
1192 return ret;
1193 }
1194
1195 mlir::Block *getEntryBlock() { return entryBlock; }
1196 };
1197
1199
1200 typedef void Destroyer(CIRGenFunction &cgf, Address addr, QualType ty);
1201
1203
1204 void pushDestroy(QualType::DestructionKind dtorKind, Address addr,
1205 QualType type);
1206
1207 void pushDestroy(CleanupKind kind, Address addr, QualType type,
1208 Destroyer *destroyer);
1209
1211
1212 /// ----------------------
1213 /// CIR emit functions
1214 /// ----------------------
1215public:
1216 mlir::Value emitAlignmentAssumption(mlir::Value ptrValue, QualType ty,
1217 SourceLocation loc,
1218 SourceLocation assumptionLoc,
1219 int64_t alignment,
1220 mlir::Value offsetValue = nullptr);
1221
1222 mlir::Value emitAlignmentAssumption(mlir::Value ptrValue, const Expr *expr,
1223 SourceLocation assumptionLoc,
1224 int64_t alignment,
1225 mlir::Value offsetValue = nullptr);
1226
1227private:
1228 void emitAndUpdateRetAlloca(clang::QualType type, mlir::Location loc,
1229 clang::CharUnits alignment);
1230
1231 CIRGenCallee emitDirectCallee(const GlobalDecl &gd);
1232
1233public:
1235 llvm::StringRef fieldName,
1236 unsigned fieldIndex);
1237
1238 mlir::Value emitAlloca(llvm::StringRef name, mlir::Type ty,
1239 mlir::Location loc, clang::CharUnits alignment,
1240 bool insertIntoFnEntryBlock,
1241 mlir::Value arraySize = nullptr);
1242 mlir::Value emitAlloca(llvm::StringRef name, mlir::Type ty,
1243 mlir::Location loc, clang::CharUnits alignment,
1244 mlir::OpBuilder::InsertPoint ip,
1245 mlir::Value arraySize = nullptr);
1246
1247 void emitAggregateStore(mlir::Value value, Address dest);
1248
1249 void emitAggExpr(const clang::Expr *e, AggValueSlot slot);
1250
1252
1253 /// Emit an aggregate copy.
1254 ///
1255 /// \param isVolatile \c true iff either the source or the destination is
1256 /// volatile.
1257 /// \param MayOverlap Whether the tail padding of the destination might be
1258 /// occupied by some other object. More efficient code can often be
1259 /// generated if not.
1260 void emitAggregateCopy(LValue dest, LValue src, QualType eltTy,
1261 AggValueSlot::Overlap_t mayOverlap,
1262 bool isVolatile = false);
1263
1264 /// Emit code to compute the specified expression which can have any type. The
1265 /// result is returned as an RValue struct. If this is an aggregate
1266 /// expression, the aggloc/agglocvolatile arguments indicate where the result
1267 /// should be returned.
1270 bool ignoreResult = false);
1271
1272 /// Emits the code necessary to evaluate an arbitrary expression into the
1273 /// given memory location.
1274 void emitAnyExprToMem(const Expr *e, Address location, Qualifiers quals,
1275 bool isInitializer);
1276
1277 /// Similarly to emitAnyExpr(), however, the result will always be accessible
1278 /// even if no aggregate location is provided.
1280
1281 void emitAnyExprToExn(const Expr *e, Address addr);
1282
1283 void emitArrayDestroy(mlir::Value begin, mlir::Value numElements,
1284 QualType elementType, CharUnits elementAlign,
1285 Destroyer *destroyer);
1286
1287 mlir::Value emitArrayLength(const clang::ArrayType *arrayType,
1288 QualType &baseType, Address &addr);
1290
1292
1294 LValueBaseInfo *baseInfo = nullptr);
1295
1296 mlir::LogicalResult emitAsmStmt(const clang::AsmStmt &s);
1297
1299 void emitAtomicInit(Expr *init, LValue dest);
1300 void emitAtomicStore(RValue rvalue, LValue dest, bool isInit);
1301 void emitAtomicStore(RValue rvalue, LValue dest, cir::MemOrder order,
1302 bool isVolatile, bool isInit);
1303
1305 mlir::OpBuilder::InsertPoint ip = {});
1306
1307 /// Emit code and set up symbol table for a variable declaration with auto,
1308 /// register, or no storage class specifier. These turn into simple stack
1309 /// objects, globals depending on target.
1310 void emitAutoVarDecl(const clang::VarDecl &d);
1311
1312 void emitAutoVarCleanups(const AutoVarEmission &emission);
1313 /// Emit the initializer for an allocated variable. If this call is not
1314 /// associated with the call to emitAutoVarAlloca (as the address of the
1315 /// emission is not directly an alloca), the allocatedSeparately parameter can
1316 /// be used to suppress the assertions. However, this should only be used in
1317 /// extreme cases, as it doesn't properly reflect the language/AST.
1318 void emitAutoVarInit(const AutoVarEmission &emission);
1319 void emitAutoVarTypeCleanup(const AutoVarEmission &emission,
1321
1322 void maybeEmitDeferredVarDeclInit(const VarDecl *vd);
1323
1324 void emitBaseInitializer(mlir::Location loc, const CXXRecordDecl *classDecl,
1325 CXXCtorInitializer *baseInit);
1326
1328
1329 cir::BrOp emitBranchThroughCleanup(mlir::Location loc, JumpDest dest);
1330
1331 mlir::LogicalResult emitBreakStmt(const clang::BreakStmt &s);
1332
1333 RValue emitBuiltinExpr(const clang::GlobalDecl &gd, unsigned builtinID,
1335
1336 /// Returns a Value corresponding to the size of the given expression by
1337 /// emitting a `cir.objsize` operation.
1338 ///
1339 /// \param e The expression whose object size to compute
1340 /// \param type Determines the semantics of the object size computation.
1341 /// The type parameter is a 2-bit value where:
1342 /// bit 0 (type & 1): 0 = whole object, 1 = closest subobject
1343 /// bit 1 (type & 2): 0 = maximum size, 2 = minimum size
1344 /// \param resType The result type for the size value
1345 /// \param emittedE Optional pre-emitted pointer value. If non-null, we'll
1346 /// call `cir.objsize` on this value rather than emitting e.
1347 /// \param isDynamic If true, allows runtime evaluation via dynamic mode
1348 mlir::Value emitBuiltinObjectSize(const clang::Expr *e, unsigned type,
1349 cir::IntType resType, mlir::Value emittedE,
1350 bool isDynamic);
1351
1352 mlir::Value evaluateOrEmitBuiltinObjectSize(const clang::Expr *e,
1353 unsigned type,
1354 cir::IntType resType,
1355 mlir::Value emittedE,
1356 bool isDynamic);
1357
1358 int64_t getAccessedFieldNo(unsigned idx, mlir::ArrayAttr elts);
1359
1360 RValue emitCall(const CIRGenFunctionInfo &funcInfo,
1362 const CallArgList &args, cir::CIRCallOpInterface *callOp,
1363 mlir::Location loc);
1366 const CallArgList &args,
1367 cir::CIRCallOpInterface *callOrTryCall = nullptr) {
1368 assert(currSrcLoc && "source location must have been set");
1369 return emitCall(funcInfo, callee, returnValue, args, callOrTryCall,
1370 *currSrcLoc);
1371 }
1372
1373 RValue emitCall(clang::QualType calleeTy, const CIRGenCallee &callee,
1375 void emitCallArg(CallArgList &args, const clang::Expr *e,
1376 clang::QualType argType);
1377 void emitCallArgs(
1378 CallArgList &args, PrototypeWrapper prototype,
1379 llvm::iterator_range<clang::CallExpr::const_arg_iterator> argRange,
1380 AbstractCallee callee = AbstractCallee(), unsigned paramsToSkip = 0);
1385
1386 template <typename T>
1387 mlir::LogicalResult emitCaseDefaultCascade(const T *stmt, mlir::Type condType,
1388 mlir::ArrayAttr value,
1389 cir::CaseOpKind kind,
1390 bool buildingTopLevelCase);
1391
1392 mlir::LogicalResult emitCaseStmt(const clang::CaseStmt &s,
1393 mlir::Type condType,
1394 bool buildingTopLevelCase);
1395
1396 LValue emitCastLValue(const CastExpr *e);
1397
1398 /// Emits an argument for a call to a `__builtin_assume`. If the builtin
1399 /// sanitizer is enabled, a runtime check is also emitted.
1400 mlir::Value emitCheckedArgForAssume(const Expr *e);
1401
1402 /// Emit a conversion from the specified complex type to the specified
1403 /// destination type, where the destination type is an LLVM scalar type.
1404 mlir::Value emitComplexToScalarConversion(mlir::Value src, QualType srcTy,
1405 QualType dstTy, SourceLocation loc);
1406
1409
1411
1412 mlir::LogicalResult emitCoroutineBody(const CoroutineBodyStmt &s);
1413 cir::CallOp emitCoroEndBuiltinCall(mlir::Location loc, mlir::Value nullPtr);
1414 cir::CallOp emitCoroIDBuiltinCall(mlir::Location loc, mlir::Value nullPtr);
1415 cir::CallOp emitCoroAllocBuiltinCall(mlir::Location loc);
1416 cir::CallOp emitCoroBeginBuiltinCall(mlir::Location loc,
1417 mlir::Value coroframeAddr);
1418
1419 void emitDestroy(Address addr, QualType type, Destroyer *destroyer);
1420
1422
1423 mlir::LogicalResult emitContinueStmt(const clang::ContinueStmt &s);
1424
1426 AggValueSlot dest);
1427
1430 Address arrayBegin, const CXXConstructExpr *e,
1431 bool newPointerIsChecked,
1432 bool zeroInitialize = false);
1434 mlir::Value numElements, Address arrayBase,
1435 const CXXConstructExpr *e,
1436 bool newPointerIsChecked,
1437 bool zeroInitialize);
1439 clang::CXXCtorType type, bool forVirtualBase,
1440 bool delegating, AggValueSlot thisAVS,
1441 const clang::CXXConstructExpr *e);
1442
1444 clang::CXXCtorType type, bool forVirtualBase,
1445 bool delegating, Address thisAddr,
1447
1448 void emitCXXDeleteExpr(const CXXDeleteExpr *e);
1449
1451 bool forVirtualBase, bool delegating,
1452 Address thisAddr, QualType thisTy);
1453
1455 mlir::Value thisVal, QualType thisTy,
1456 mlir::Value implicitParam,
1457 QualType implicitParamTy, const CallExpr *e);
1458
1459 mlir::LogicalResult emitCXXForRangeStmt(const CXXForRangeStmt &s,
1461
1464
1466 const clang::CXXMethodDecl *md, const CIRGenCallee &callee,
1467 ReturnValueSlot returnValue, mlir::Value thisPtr,
1468 mlir::Value implicitParam, clang::QualType implicitParamTy,
1469 const clang::CallExpr *ce, CallArgList *rtlArgs);
1470
1472 const clang::CallExpr *ce, const clang::CXXMethodDecl *md,
1473 ReturnValueSlot returnValue, bool hasQualifier,
1474 clang::NestedNameSpecifier qualifier, bool isArrow,
1475 const clang::Expr *base);
1476
1477 mlir::Value emitCXXNewExpr(const CXXNewExpr *e);
1478
1479 void emitNewArrayInitializer(const CXXNewExpr *e, QualType elementType,
1480 mlir::Type elementTy, Address beginPtr,
1481 mlir::Value numElements,
1482 mlir::Value allocSizeWithoutCookie);
1483
1485 const CXXMethodDecl *md,
1487
1489
1490 void emitCXXTemporary(const CXXTemporary *temporary, QualType tempType,
1491 Address ptr);
1492
1493 void emitCXXThrowExpr(const CXXThrowExpr *e);
1494
1495 mlir::LogicalResult emitCXXTryStmt(const clang::CXXTryStmt &s);
1496
1497 mlir::LogicalResult emitCXXTryStmtUnderScope(const clang::CXXTryStmt &s);
1498
1499 void enterCXXTryStmt(const CXXTryStmt &s, cir::TryOp tryOp,
1500 bool isFnTryBlock = false);
1501
1502 void exitCXXTryStmt(const CXXTryStmt &s, bool isFnTryBlock = false);
1503
1505 clang::CXXCtorType ctorType, FunctionArgList &args);
1506
1507 // It's important not to confuse this and emitDelegateCXXConstructorCall.
1508 // Delegating constructors are the C++11 feature. The constructor delegate
1509 // optimization is used to reduce duplication in the base and complete
1510 // constructors where they are substantially the same.
1512 const FunctionArgList &args);
1513
1514 void emitDeleteCall(const FunctionDecl *deleteFD, mlir::Value ptr,
1515 QualType deleteTy);
1516
1517 mlir::LogicalResult emitDoStmt(const clang::DoStmt &s);
1518
1519 mlir::Value emitDynamicCast(Address thisAddr, const CXXDynamicCastExpr *dce);
1520
1521 /// Emit an expression as an initializer for an object (variable, field, etc.)
1522 /// at the given location. The expression is not necessarily the normal
1523 /// initializer for the object, and the address is not necessarily
1524 /// its normal location.
1525 ///
1526 /// \param init the initializing expression
1527 /// \param d the object to act as if we're initializing
1528 /// \param lvalue the lvalue to initialize
1529 /// \param capturedByInit true if \p d is a __block variable whose address is
1530 /// potentially changed by the initializer
1531 void emitExprAsInit(const clang::Expr *init, const clang::ValueDecl *d,
1532 LValue lvalue, bool capturedByInit = false);
1533
1534 mlir::LogicalResult emitFunctionBody(const clang::Stmt *body);
1535
1536 mlir::LogicalResult emitGotoStmt(const clang::GotoStmt &s);
1537
1539
1541 clang::Expr *init);
1542
1544
1545 mlir::Value emitPromotedComplexExpr(const Expr *e, QualType promotionType);
1546
1547 mlir::Value emitPromotedScalarExpr(const Expr *e, QualType promotionType);
1548
1549 mlir::Value emitPromotedValue(mlir::Value result, QualType promotionType);
1550
1551 void emitReturnOfRValue(mlir::Location loc, RValue rv, QualType ty);
1552
1553 mlir::Value emitRuntimeCall(mlir::Location loc, cir::FuncOp callee,
1554 llvm::ArrayRef<mlir::Value> args = {});
1555
1556 /// Emit the computation of the specified expression of scalar type.
1557 mlir::Value emitScalarExpr(const clang::Expr *e,
1558 bool ignoreResultAssign = false);
1559
1560 mlir::Value emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv,
1561 cir::UnaryOpKind kind, bool isPre);
1562
1563 /// Build a debug stoppoint if we are emitting debug info.
1564 void emitStopPoint(const Stmt *s);
1565
1566 // Build CIR for a statement. useCurrentScope should be true if no
1567 // new scopes need be created when finding a compound statement.
1568 mlir::LogicalResult emitStmt(const clang::Stmt *s, bool useCurrentScope,
1569 llvm::ArrayRef<const Attr *> attrs = {});
1570
1571 mlir::LogicalResult emitSimpleStmt(const clang::Stmt *s,
1572 bool useCurrentScope);
1573
1574 mlir::LogicalResult emitForStmt(const clang::ForStmt &s);
1575
1576 void emitForwardingCallToLambda(const CXXMethodDecl *lambdaCallOperator,
1577 CallArgList &callArgs);
1578
1579 RValue emitCoawaitExpr(const CoawaitExpr &e,
1580 AggValueSlot aggSlot = AggValueSlot::ignored(),
1581 bool ignoreResult = false);
1582 /// Emit the computation of the specified expression of complex type,
1583 /// returning the result.
1584 mlir::Value emitComplexExpr(const Expr *e);
1585
1586 void emitComplexExprIntoLValue(const Expr *e, LValue dest, bool isInit);
1587
1588 mlir::Value emitComplexPrePostIncDec(const UnaryOperator *e, LValue lv,
1589 cir::UnaryOpKind op, bool isPre);
1590
1594 mlir::Value &result);
1595
1596 mlir::LogicalResult
1597 emitCompoundStmt(const clang::CompoundStmt &s, Address *lastValue = nullptr,
1598 AggValueSlot slot = AggValueSlot::ignored());
1599
1600 mlir::LogicalResult
1602 Address *lastValue = nullptr,
1603 AggValueSlot slot = AggValueSlot::ignored());
1604
1605 void emitDecl(const clang::Decl &d, bool evaluateConditionDecl = false);
1606 mlir::LogicalResult emitDeclStmt(const clang::DeclStmt &s);
1607 LValue emitDeclRefLValue(const clang::DeclRefExpr *e);
1608
1609 mlir::LogicalResult emitDefaultStmt(const clang::DefaultStmt &s,
1610 mlir::Type condType,
1611 bool buildingTopLevelCase);
1612
1614 clang::CXXCtorType ctorType,
1615 const FunctionArgList &args,
1617
1618 /// We are performing a delegate call; that is, the current function is
1619 /// delegating to another one. Produce a r-value suitable for passing the
1620 /// given parameter.
1621 void emitDelegateCallArg(CallArgList &args, const clang::VarDecl *param,
1623
1624 /// Emit an `if` on a boolean condition to the specified blocks.
1625 /// FIXME: Based on the condition, this might try to simplify the codegen of
1626 /// the conditional based on the branch.
1627 /// In the future, we may apply code generation simplifications here,
1628 /// similar to those used in classic LLVM codegen
1629 /// See `EmitBranchOnBoolExpr` for inspiration.
1630 mlir::LogicalResult emitIfOnBoolExpr(const clang::Expr *cond,
1631 const clang::Stmt *thenS,
1632 const clang::Stmt *elseS);
1633 cir::IfOp emitIfOnBoolExpr(const clang::Expr *cond,
1634 BuilderCallbackRef thenBuilder,
1635 mlir::Location thenLoc,
1636 BuilderCallbackRef elseBuilder,
1637 std::optional<mlir::Location> elseLoc = {});
1638
1639 mlir::Value emitOpOnBoolExpr(mlir::Location loc, const clang::Expr *cond);
1640
1641 mlir::LogicalResult emitLabel(const clang::LabelDecl &d);
1642 mlir::LogicalResult emitLabelStmt(const clang::LabelStmt &s);
1643
1644 void emitLambdaDelegatingInvokeBody(const CXXMethodDecl *md);
1645 void emitLambdaStaticInvokeBody(const CXXMethodDecl *md);
1646
1647 void populateCatchHandlers(cir::TryOp tryOp);
1648
1649 mlir::LogicalResult emitIfStmt(const clang::IfStmt &s);
1650
1651 /// Emit code to compute the specified expression,
1652 /// ignoring the result.
1653 void emitIgnoredExpr(const clang::Expr *e);
1654
1655 RValue emitLoadOfBitfieldLValue(LValue lv, SourceLocation loc);
1656
1657 /// Load a complex number from the specified l-value.
1658 mlir::Value emitLoadOfComplex(LValue src, SourceLocation loc);
1659
1660 RValue emitLoadOfExtVectorElementLValue(LValue lv);
1661
1662 /// Given an expression that represents a value lvalue, this method emits
1663 /// the address of the lvalue, then loads the result as an rvalue,
1664 /// returning the rvalue.
1665 RValue emitLoadOfLValue(LValue lv, SourceLocation loc);
1666
1667 Address emitLoadOfReference(LValue refLVal, mlir::Location loc,
1668 LValueBaseInfo *pointeeBaseInfo);
1669 LValue emitLoadOfReferenceLValue(Address refAddr, mlir::Location loc,
1670 QualType refTy, AlignmentSource source);
1671
1672 /// EmitLoadOfScalar - Load a scalar value from an address, taking
1673 /// care to appropriately convert from the memory representation to
1674 /// the LLVM value representation. The l-value must be a simple
1675 /// l-value.
1676 mlir::Value emitLoadOfScalar(LValue lvalue, SourceLocation loc);
1677 mlir::Value emitLoadOfScalar(Address addr, bool isVolatile, QualType ty,
1678 SourceLocation loc, LValueBaseInfo baseInfo);
1679
1680 /// Emit code to compute a designator that specifies the location
1681 /// of the expression.
1682 /// FIXME: document this function better.
1683 LValue emitLValue(const clang::Expr *e);
1684 LValue emitLValueForBitField(LValue base, const FieldDecl *field);
1685 LValue emitLValueForField(LValue base, const clang::FieldDecl *field);
1686
1687 LValue emitLValueForLambdaField(const FieldDecl *field);
1688 LValue emitLValueForLambdaField(const FieldDecl *field,
1689 mlir::Value thisValue);
1690
1691 /// Like emitLValueForField, excpet that if the Field is a reference, this
1692 /// will return the address of the reference and not the address of the value
1693 /// stored in the reference.
1694 LValue emitLValueForFieldInitialization(LValue base,
1695 const clang::FieldDecl *field,
1696 llvm::StringRef fieldName);
1697
1698 LValue emitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *e);
1699
1700 LValue emitMemberExpr(const MemberExpr *e);
1701
1702 LValue emitOpaqueValueLValue(const OpaqueValueExpr *e);
1703
1704 LValue emitConditionalOperatorLValue(const AbstractConditionalOperator *expr);
1705
1706 /// Given an expression with a pointer type, emit the value and compute our
1707 /// best estimate of the alignment of the pointee.
1708 ///
1709 /// One reasonable way to use this information is when there's a language
1710 /// guarantee that the pointer must be aligned to some stricter value, and
1711 /// we're simply trying to ensure that sufficiently obvious uses of under-
1712 /// aligned objects don't get miscompiled; for example, a placement new
1713 /// into the address of a local variable. In such a case, it's quite
1714 /// reasonable to just ignore the returned alignment when it isn't from an
1715 /// explicit source.
1717 LValueBaseInfo *baseInfo = nullptr);
1718
1719 /// Emits a reference binding to the passed in expression.
1720 RValue emitReferenceBindingToExpr(const Expr *e);
1721
1722 mlir::LogicalResult emitReturnStmt(const clang::ReturnStmt &s);
1723
1724 RValue emitRotate(const CallExpr *e, bool isRotateLeft);
1725
1726 mlir::Value emitScalarConstant(const ConstantEmission &constant, Expr *e);
1727
1728 /// Emit a conversion from the specified type to the specified destination
1729 /// type, both of which are CIR scalar types.
1730 mlir::Value emitScalarConversion(mlir::Value src, clang::QualType srcType,
1731 clang::QualType dstType,
1733
1734 void emitScalarInit(const clang::Expr *init, mlir::Location loc,
1735 LValue lvalue, bool capturedByInit = false);
1736
1737 mlir::Value emitScalarOrConstFoldImmArg(unsigned iceArguments, unsigned idx,
1738 const Expr *argExpr);
1739
1740 void emitStaticVarDecl(const VarDecl &d, cir::GlobalLinkageKind linkage);
1741
1742 void emitStoreOfComplex(mlir::Location loc, mlir::Value v, LValue dest,
1743 bool isInit);
1744
1745 void emitStoreOfScalar(mlir::Value value, Address addr, bool isVolatile,
1746 clang::QualType ty, LValueBaseInfo baseInfo,
1747 bool isInit = false, bool isNontemporal = false);
1748 void emitStoreOfScalar(mlir::Value value, LValue lvalue, bool isInit);
1749
1750 /// Store the specified rvalue into the specified
1751 /// lvalue, where both are guaranteed to the have the same type, and that type
1752 /// is 'Ty'.
1753 void emitStoreThroughLValue(RValue src, LValue dst, bool isInit = false);
1754
1755 mlir::Value emitStoreThroughBitfieldLValue(RValue src, LValue dstresult);
1756
1757 LValue emitStringLiteralLValue(const StringLiteral *e,
1758 llvm::StringRef name = ".str");
1759
1760 mlir::LogicalResult emitSwitchBody(const clang::Stmt *s);
1761 mlir::LogicalResult emitSwitchCase(const clang::SwitchCase &s,
1762 bool buildingTopLevelCase);
1763 mlir::LogicalResult emitSwitchStmt(const clang::SwitchStmt &s);
1764
1765 mlir::Value emitTargetBuiltinExpr(unsigned builtinID,
1766 const clang::CallExpr *e,
1767 ReturnValueSlot &returnValue);
1768
1769 /// Given a value and its clang type, returns the value casted to its memory
1770 /// representation.
1771 /// Note: CIR defers most of the special casting to the final lowering passes
1772 /// to conserve the high level information.
1773 mlir::Value emitToMemory(mlir::Value value, clang::QualType ty);
1774
1775 /// Emit a trap instruction, which is used to abort the program in an abnormal
1776 /// way, usually for debugging purposes.
1777 /// \p createNewBlock indicates whether to create a new block for the IR
1778 /// builder. Since the `cir.trap` operation is a terminator, operations that
1779 /// follow a trap cannot be emitted after `cir.trap` in the same block. To
1780 /// ensure these operations get emitted successfully, you need to create a new
1781 /// dummy block and set the insertion point there before continuing from the
1782 /// trap operation.
1783 void emitTrap(mlir::Location loc, bool createNewBlock);
1784
1785 LValue emitUnaryOpLValue(const clang::UnaryOperator *e);
1786
1787 mlir::Value emitUnPromotedValue(mlir::Value result, QualType unPromotionType);
1788
1789 /// Emit a reached-unreachable diagnostic if \p loc is valid and runtime
1790 /// checking is enabled. Otherwise, just emit an unreachable instruction.
1791 /// \p createNewBlock indicates whether to create a new block for the IR
1792 /// builder. Since the `cir.unreachable` operation is a terminator, operations
1793 /// that follow an unreachable point cannot be emitted after `cir.unreachable`
1794 /// in the same block. To ensure these operations get emitted successfully,
1795 /// you need to create a dummy block and set the insertion point there before
1796 /// continuing from the unreachable point.
1797 void emitUnreachable(clang::SourceLocation loc, bool createNewBlock);
1798
1799 /// This method handles emission of any variable declaration
1800 /// inside a function, including static vars etc.
1801 void emitVarDecl(const clang::VarDecl &d);
1802
1803 void emitVariablyModifiedType(QualType ty);
1804
1805 mlir::LogicalResult emitWhileStmt(const clang::WhileStmt &s);
1806
1807 mlir::Value emitX86BuiltinExpr(unsigned builtinID, const CallExpr *e);
1808
1809 /// Given an assignment `*lhs = rhs`, emit a test that checks if \p rhs is
1810 /// nonnull, if 1\p LHS is marked _Nonnull.
1811 void emitNullabilityCheck(LValue lhs, mlir::Value rhs,
1813
1814 /// An object to manage conditionally-evaluated expressions.
1816 CIRGenFunction &cgf;
1817 mlir::OpBuilder::InsertPoint insertPt;
1818
1819 public:
1821 : cgf(cgf), insertPt(cgf.builder.saveInsertionPoint()) {}
1822 ConditionalEvaluation(CIRGenFunction &cgf, mlir::OpBuilder::InsertPoint ip)
1823 : cgf(cgf), insertPt(ip) {}
1824
1826 assert(cgf.outermostConditional != this);
1827 if (!cgf.outermostConditional)
1828 cgf.outermostConditional = this;
1829 }
1830
1832 assert(cgf.outermostConditional != nullptr);
1833 if (cgf.outermostConditional == this)
1834 cgf.outermostConditional = nullptr;
1835 }
1836
1837 /// Returns the insertion point which will be executed prior to each
1838 /// evaluation of the conditional code. In LLVM OG, this method
1839 /// is called getStartingBlock.
1840 mlir::OpBuilder::InsertPoint getInsertPoint() const { return insertPt; }
1841 };
1842
1844 std::optional<LValue> lhs{}, rhs{};
1845 mlir::Value result{};
1846 };
1847
1848 // Return true if we're currently emitting one branch or the other of a
1849 // conditional expression.
1850 bool isInConditionalBranch() const { return outermostConditional != nullptr; }
1851
1852 void setBeforeOutermostConditional(mlir::Value value, Address addr) {
1853 assert(isInConditionalBranch());
1854 {
1855 mlir::OpBuilder::InsertionGuard guard(builder);
1856 builder.restoreInsertionPoint(outermostConditional->getInsertPoint());
1857 builder.createStore(
1858 value.getLoc(), value, addr, /*isVolatile=*/false,
1859 mlir::IntegerAttr::get(
1860 mlir::IntegerType::get(value.getContext(), 64),
1861 (uint64_t)addr.getAlignment().getAsAlign().value()));
1862 }
1863 }
1864
1865 // Points to the outermost active conditional control. This is used so that
1866 // we know if a temporary should be destroyed conditionally.
1868
1869 /// An RAII object to record that we're evaluating a statement
1870 /// expression.
1872 CIRGenFunction &cgf;
1873
1874 /// We have to save the outermost conditional: cleanups in a
1875 /// statement expression aren't conditional just because the
1876 /// StmtExpr is.
1877 ConditionalEvaluation *savedOutermostConditional;
1878
1879 public:
1881 : cgf(cgf), savedOutermostConditional(cgf.outermostConditional) {
1882 cgf.outermostConditional = nullptr;
1883 }
1884
1886 cgf.outermostConditional = savedOutermostConditional;
1887 }
1888 };
1889
1890 template <typename FuncTy>
1891 ConditionalInfo emitConditionalBlocks(const AbstractConditionalOperator *e,
1892 const FuncTy &branchGenFunc);
1893
1894 mlir::Value emitTernaryOnBoolExpr(const clang::Expr *cond, mlir::Location loc,
1895 const clang::Stmt *thenS,
1896 const clang::Stmt *elseS);
1897
1898 /// Build a "reference" to a va_list; this is either the address or the value
1899 /// of the expression, depending on how va_list is defined.
1900 Address emitVAListRef(const Expr *e);
1901
1902 /// Emits the start of a CIR variable-argument operation (`cir.va_start`)
1903 ///
1904 /// \param vaList A reference to the \c va_list as emitted by either
1905 /// \c emitVAListRef or \c emitMSVAListRef.
1906 ///
1907 /// \param count The number of arguments in \c vaList
1908 void emitVAStart(mlir::Value vaList, mlir::Value count);
1909
1910 /// Emits the end of a CIR variable-argument operation (`cir.va_start`)
1911 ///
1912 /// \param vaList A reference to the \c va_list as emitted by either
1913 /// \c emitVAListRef or \c emitMSVAListRef.
1914 void emitVAEnd(mlir::Value vaList);
1915
1916 /// Generate code to get an argument from the passed in pointer
1917 /// and update it accordingly.
1918 ///
1919 /// \param ve The \c VAArgExpr for which to generate code.
1920 ///
1921 /// \param vaListAddr Receives a reference to the \c va_list as emitted by
1922 /// either \c emitVAListRef or \c emitMSVAListRef.
1923 ///
1924 /// \returns SSA value with the argument.
1925 mlir::Value emitVAArg(VAArgExpr *ve);
1926
1927 /// ----------------------
1928 /// CIR build helpers
1929 /// -----------------
1930public:
1931 cir::AllocaOp createTempAlloca(mlir::Type ty, mlir::Location loc,
1932 const Twine &name = "tmp",
1933 mlir::Value arraySize = nullptr,
1934 bool insertIntoFnEntryBlock = false);
1935 cir::AllocaOp createTempAlloca(mlir::Type ty, mlir::Location loc,
1936 const Twine &name = "tmp",
1937 mlir::OpBuilder::InsertPoint ip = {},
1938 mlir::Value arraySize = nullptr);
1939 Address createTempAlloca(mlir::Type ty, CharUnits align, mlir::Location loc,
1940 const Twine &name = "tmp",
1941 mlir::Value arraySize = nullptr,
1942 Address *alloca = nullptr,
1943 mlir::OpBuilder::InsertPoint ip = {});
1944 Address createTempAllocaWithoutCast(mlir::Type ty, CharUnits align,
1945 mlir::Location loc,
1946 const Twine &name = "tmp",
1947 mlir::Value arraySize = nullptr,
1948 mlir::OpBuilder::InsertPoint ip = {});
1949
1950 /// Create a temporary memory object of the given type, with
1951 /// appropriate alignmen and cast it to the default address space. Returns
1952 /// the original alloca instruction by \p Alloca if it is not nullptr.
1953 Address createMemTemp(QualType t, mlir::Location loc,
1954 const Twine &name = "tmp", Address *alloca = nullptr,
1955 mlir::OpBuilder::InsertPoint ip = {});
1956 Address createMemTemp(QualType t, CharUnits align, mlir::Location loc,
1957 const Twine &name = "tmp", Address *alloca = nullptr,
1958 mlir::OpBuilder::InsertPoint ip = {});
1959
1960 //===--------------------------------------------------------------------===//
1961 // OpenACC Emission
1962 //===--------------------------------------------------------------------===//
1963private:
1964 template <typename Op>
1965 Op emitOpenACCOp(mlir::Location start, OpenACCDirectiveKind dirKind,
1966 SourceLocation dirLoc,
1967 llvm::ArrayRef<const OpenACCClause *> clauses);
1968 // Function to do the basic implementation of an operation with an Associated
1969 // Statement. Models AssociatedStmtConstruct.
1970 template <typename Op, typename TermOp>
1971 mlir::LogicalResult emitOpenACCOpAssociatedStmt(
1972 mlir::Location start, mlir::Location end, OpenACCDirectiveKind dirKind,
1973 SourceLocation dirLoc, llvm::ArrayRef<const OpenACCClause *> clauses,
1974 const Stmt *associatedStmt);
1975
1976 template <typename Op, typename TermOp>
1977 mlir::LogicalResult emitOpenACCOpCombinedConstruct(
1978 mlir::Location start, mlir::Location end, OpenACCDirectiveKind dirKind,
1979 SourceLocation dirLoc, llvm::ArrayRef<const OpenACCClause *> clauses,
1980 const Stmt *loopStmt);
1981
1982 template <typename Op>
1983 void emitOpenACCClauses(Op &op, OpenACCDirectiveKind dirKind,
1984 SourceLocation dirLoc,
1985 ArrayRef<const OpenACCClause *> clauses);
1986 // The second template argument doesn't need to be a template, since it should
1987 // always be an mlir::acc::LoopOp, but as this is a template anyway, we make
1988 // it a template argument as this way we can avoid including the OpenACC MLIR
1989 // headers here. We will count on linker failures/explicit instantiation to
1990 // ensure we don't mess this up, but it is only called from 1 place, and
1991 // instantiated 3x.
1992 template <typename ComputeOp, typename LoopOp>
1993 void emitOpenACCClauses(ComputeOp &op, LoopOp &loopOp,
1994 OpenACCDirectiveKind dirKind, SourceLocation dirLoc,
1995 ArrayRef<const OpenACCClause *> clauses);
1996
1997 // The OpenACC LoopOp requires that we have auto, seq, or independent on all
1998 // LoopOp operations for the 'none' device type case. This function checks if
1999 // the LoopOp has one, else it updates it to have one.
2000 void updateLoopOpParallelism(mlir::acc::LoopOp &op, bool isOrphan,
2002
2003 // The OpenACC 'cache' construct actually applies to the 'loop' if present. So
2004 // keep track of the 'loop' so that we can add the cache vars to it correctly.
2005 mlir::acc::LoopOp *activeLoopOp = nullptr;
2006
2007 struct ActiveOpenACCLoopRAII {
2008 CIRGenFunction &cgf;
2009 mlir::acc::LoopOp *oldLoopOp;
2010
2011 ActiveOpenACCLoopRAII(CIRGenFunction &cgf, mlir::acc::LoopOp *newOp)
2012 : cgf(cgf), oldLoopOp(cgf.activeLoopOp) {
2013 cgf.activeLoopOp = newOp;
2014 }
2015 ~ActiveOpenACCLoopRAII() { cgf.activeLoopOp = oldLoopOp; }
2016 };
2017
2018 // Keep track of the last place we inserted a 'recipe' so that we can insert
2019 // the next one in lexical order.
2020 mlir::OpBuilder::InsertPoint lastRecipeLocation;
2021
2022public:
2023 // Helper type used to store the list of important information for a 'data'
2024 // clause variable, or a 'cache' variable reference.
2026 mlir::Location beginLoc;
2027 mlir::Value varValue;
2028 std::string name;
2029 // The type of the original variable reference: that is, after 'bounds' have
2030 // removed pointers/array types/etc. So in the case of int arr[5], and a
2031 // private(arr[1]), 'origType' is 'int', but 'baseType' is 'int[5]'.
2035 // The list of types that we found when going through the bounds, which we
2036 // can use to properly set the alloca section.
2038 };
2039
2040 // Gets the collection of info required to lower and OpenACC clause or cache
2041 // construct variable reference.
2043 // Helper function to emit the integer expressions as required by an OpenACC
2044 // clause/construct.
2045 mlir::Value emitOpenACCIntExpr(const Expr *intExpr);
2046 // Helper function to emit an integer constant as an mlir int type, used for
2047 // constants in OpenACC constructs/clauses.
2048 mlir::Value createOpenACCConstantInt(mlir::Location loc, unsigned width,
2049 int64_t value);
2050
2051 mlir::LogicalResult
2053 mlir::LogicalResult emitOpenACCLoopConstruct(const OpenACCLoopConstruct &s);
2054 mlir::LogicalResult
2056 mlir::LogicalResult emitOpenACCDataConstruct(const OpenACCDataConstruct &s);
2057 mlir::LogicalResult
2059 mlir::LogicalResult
2061 mlir::LogicalResult
2063 mlir::LogicalResult emitOpenACCWaitConstruct(const OpenACCWaitConstruct &s);
2064 mlir::LogicalResult emitOpenACCInitConstruct(const OpenACCInitConstruct &s);
2065 mlir::LogicalResult
2067 mlir::LogicalResult emitOpenACCSetConstruct(const OpenACCSetConstruct &s);
2068 mlir::LogicalResult
2070 mlir::LogicalResult
2072 mlir::LogicalResult emitOpenACCCacheConstruct(const OpenACCCacheConstruct &s);
2073
2076
2077 /// Create a temporary memory object for the given aggregate type.
2078 AggValueSlot createAggTemp(QualType ty, mlir::Location loc,
2079 const Twine &name = "tmp",
2080 Address *alloca = nullptr) {
2082 return AggValueSlot::forAddr(
2083 createMemTemp(ty, loc, name, alloca), ty.getQualifiers(),
2086 }
2087
2088private:
2089 QualType getVarArgType(const Expr *arg);
2090};
2091
2092} // namespace clang::CIRGen
2093
2094#endif
Defines the clang::ASTContext interface.
llvm::function_ref< void(mlir::OpBuilder &, mlir::Location)> BuilderCallbackRef
Definition CIRDialect.h:37
Defines the clang::Expr interface and subclasses for C++ expressions.
C Language Family Type Representation.
__device__ __2f16 b
__device__ __2f16 float __ockl_bool s
__device__ __2f16 float c
Represents a member of a struct/union/class.
Definition Decl.h:3160
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:220
AbstractConditionalOperator - An abstract base class for ConditionalOperator and BinaryConditionalOpe...
Definition Expr.h:4287
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Definition Expr.h:2721
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition TypeBase.h:3722
AsmStmt is the base class for GCCAsmStmt and MSAsmStmt.
Definition Stmt.h:3215
AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*, __atomic_load,...
Definition Expr.h:6814
BinaryConditionalOperator - The GNU extension to the conditional operator which allows the middle ope...
Definition Expr.h:4387
OpaqueValueExpr * getOpaqueValue() const
getOpaqueValue - Return the opaque value placeholder.
Definition Expr.h:4425
Expr * getCommon() const
getCommon - Return the common expression, written to the left of the condition.
Definition Expr.h:4422
A builtin binary operation expression such as "x + y" or "x <= y".
Definition Expr.h:3972
BreakStmt - This represents a break.
Definition Stmt.h:3114
mlir::Value getPointer() const
Definition Address.h:84
static Address invalid()
Definition Address.h:69
clang::CharUnits getAlignment() const
Definition Address.h:124
mlir::Value getBasePointer() const
Definition Address.h:89
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.
AbstractCallee(const clang::FunctionDecl *fd)
const clang::ParmVarDecl * getParamDecl(unsigned I) const
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)
FieldConstructionScope(CIRGenFunction &cgf, Address thisAddr)
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...
RunCleanupsScope(CIRGenFunction &cgf)
Enter a new cleanup scope.
void forceCleanup()
Force the emission of cleanups now, instead of waiting until this object is destroyed.
~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 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,...
cir::CallOp emitCoroIDBuiltinCall(mlir::Location loc, mlir::Value nullPtr)
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::Value emitCheckedArgForAssume(const Expr *e)
Emits an argument for a call to a __builtin_assume.
LValue emitOpaqueValueLValue(const OpaqueValueExpr *e)
mlir::LogicalResult emitDoStmt(const clang::DoStmt &s)
static cir::TypeEvaluationKind getEvaluationKind(clang::QualType type)
Return the cir::TypeEvaluationKind of QualType type.
clang::GlobalDecl curGD
The GlobalDecl for the current function being compiled or the global variable currently being initial...
clang::CurrentSourceLocExprScope::SourceLocExprScopeGuard SourceLocExprScopeGuard
RValue convertTempToRValue(Address addr, clang::QualType type, clang::SourceLocation loc)
Given the address of a temporary variable, produce an r-value of its type.
mlir::LogicalResult 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)
mlir::LogicalResult emitOpenACCWaitConstruct(const OpenACCWaitConstruct &s)
cir::FuncOp generateCode(clang::GlobalDecl gd, cir::FuncOp fn, cir::FuncType funcType)
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 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 enterCXXTryStmt(const CXXTryStmt &s, cir::TryOp tryOp, bool isFnTryBlock=false)
RValue emitCXXMemberCallExpr(const clang::CXXMemberCallExpr *e, ReturnValueSlot returnValue)
mlir::LogicalResult emitOpenACCUpdateConstruct(const OpenACCUpdateConstruct &s)
LValue emitLValueForBitField(LValue base, const FieldDecl *field)
mlir::LogicalResult emitIfOnBoolExpr(const clang::Expr *cond, const clang::Stmt *thenS, const clang::Stmt *elseS)
Emit an if on a boolean condition to the specified blocks.
VlaSizePair getVLASize(const VariableArrayType *type)
Returns an MLIR::Value+QualType pair that corresponds to the size, in non-variably-sized elements,...
LValue emitScalarCompoundAssignWithComplex(const CompoundAssignOperator *e, mlir::Value &result)
void populateEHCatchRegions(EHScopeStack::stable_iterator scope, cir::TryOp tryOp)
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.
void exitCXXTryStmt(const CXXTryStmt &s, bool isFnTryBlock=false)
void setBeforeOutermostConditional(mlir::Value value, Address addr)
mlir::LogicalResult emitOpenACCCacheConstruct(const OpenACCCacheConstruct &s)
mlir::Value loadCXXThis()
Load the value for 'this'.
LValue makeNaturalAlignPointeeAddrLValue(mlir::Value v, clang::QualType t)
Given a value of type T* that may not be to a complete object, construct an l-vlaue withi the natural...
RValue emitCallExpr(const clang::CallExpr *e, ReturnValueSlot returnValue=ReturnValueSlot())
void emitDeleteCall(const FunctionDecl *deleteFD, mlir::Value ptr, QualType deleteTy)
LValue emitMemberExpr(const MemberExpr *e)
const TargetInfo & getTarget() const
void replaceAddrOfLocalVar(const clang::VarDecl *vd, Address addr)
llvm::DenseMap< const clang::Decl *, Address > DeclMapTy
LValue emitConditionalOperatorLValue(const AbstractConditionalOperator *expr)
LValue emitLValue(const clang::Expr *e)
Emit code to compute a designator that specifies the location of the expression.
Address makeNaturalAddressForPointer(mlir::Value ptr, QualType t, CharUnits alignment, bool forPointeeType=false, LValueBaseInfo *baseInfo=nullptr)
Construct an address with the natural alignment of T.
const clang::Decl * curFuncDecl
mlir::LogicalResult emitCXXForRangeStmt(const CXXForRangeStmt &s, llvm::ArrayRef< const Attr * > attrs)
LValue emitLValueForLambdaField(const FieldDecl *field)
RValue emitCall(const CIRGenFunctionInfo &funcInfo, const CIRGenCallee &callee, ReturnValueSlot returnValue, const CallArgList &args, cir::CIRCallOpInterface *callOrTryCall=nullptr)
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)
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 emitTargetBuiltinExpr(unsigned builtinID, const clang::CallExpr *e, ReturnValueSlot &returnValue)
Address getAsNaturalAddressOf(Address addr, QualType pointeeTy)
JumpDest returnBlock(mlir::Block *retBlock)
Unified return block.
LValue emitComplexCompoundAssignmentLValue(const CompoundAssignOperator *e)
mlir::Value getVTTParameter(GlobalDecl gd, bool forVirtualBase, bool delegating)
Return the VTT parameter that should be passed to a base constructor/destructor with virtual bases.
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
void initializeVTablePointers(mlir::Location loc, const clang::CXXRecordDecl *rd)
mlir::Type convertType(const TypeDecl *t)
bool constantFoldsToBool(const clang::Expr *cond, bool &resultBool, bool allowLabels=false)
If the specified expression does not fold to a constant, or if it does but contains a label,...
mlir::Value emitOpOnBoolExpr(mlir::Location loc, const clang::Expr *cond)
TODO(cir): see EmitBranchOnBoolExpr for extra ideas).
void initializeVTablePointer(mlir::Location loc, const VPtr &vptr)
Address getAddressOfBaseClass(Address value, const CXXRecordDecl *derived, llvm::iterator_range< CastExpr::path_const_iterator > path, bool nullCheckValue, SourceLocation loc)
void emitAggregateStore(mlir::Value value, Address dest)
mlir::LogicalResult emitReturnStmt(const clang::ReturnStmt &s)
LValue emitLoadOfReferenceLValue(Address refAddr, mlir::Location loc, QualType refTy, AlignmentSource source)
void emitDelegateCXXConstructorCall(const clang::CXXConstructorDecl *ctor, clang::CXXCtorType ctorType, const FunctionArgList &args, clang::SourceLocation loc)
mlir::Value emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv, cir::UnaryOpKind kind, bool isPre)
ConditionalEvaluation * outermostConditional
mlir::LogicalResult emitOpenACCInitConstruct(const OpenACCInitConstruct &s)
void emitAnyExprToMem(const Expr *e, Address location, Qualifiers quals, bool isInitializer)
Emits the code necessary to evaluate an arbitrary expression into the given memory location.
RValue emitCXXMemberOrOperatorCall(const clang::CXXMethodDecl *md, const CIRGenCallee &callee, ReturnValueSlot returnValue, mlir::Value thisPtr, mlir::Value implicitParam, clang::QualType implicitParamTy, const clang::CallExpr *ce, CallArgList *rtlArgs)
LValue getOrCreateOpaqueLValueMapping(const OpaqueValueExpr *e)
Given an opaque value expression, return its LValue mapping if it exists, otherwise create one.
void emitBaseInitializer(mlir::Location loc, const CXXRecordDecl *classDecl, CXXCtorInitializer *baseInit)
RValue emitAtomicExpr(AtomicExpr *e)
void emitExprAsInit(const clang::Expr *init, const clang::ValueDecl *d, LValue lvalue, bool capturedByInit=false)
Emit an expression as an initializer for an object (variable, field, etc.) at the given location.
mlir::LogicalResult emitCXXTryStmtUnderScope(const clang::CXXTryStmt &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 emitOpenACCSetConstruct(const OpenACCSetConstruct &s)
RValue emitReferenceBindingToExpr(const Expr *e)
Emits a reference binding to the passed in expression.
void emitVAStart(mlir::Value vaList, mlir::Value count)
Emits the start of a CIR variable-argument operation (cir.va_start)
VPtrsVector getVTablePointers(const clang::CXXRecordDecl *vtableClass)
const TargetCIRGenInfo & getTargetHooks() const
mlir::LogicalResult emitSwitchStmt(const clang::SwitchStmt &s)
mlir::Value evaluateOrEmitBuiltinObjectSize(const clang::Expr *e, unsigned type, cir::IntType resType, mlir::Value emittedE, bool isDynamic)
JumpDest getJumpDestInCurrentScope(mlir::Block *target)
The given basic block lies in the current EH scope, but may be a target of a potentially scope-crossi...
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)
CleanupKind getCleanupKind(QualType::DestructionKind kind)
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....
AggValueSlot::Overlap_t getOverlapForFieldInit(const FieldDecl *fd)
mlir::LogicalResult emitSimpleStmt(const clang::Stmt *s, bool useCurrentScope)
mlir::Operation * curFn
The current function or global initializer that is generated code for.
mlir::LogicalResult emitAsmStmt(const clang::AsmStmt &s)
Definition CIRGenAsm.cpp:86
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::Value emitPromotedComplexExpr(const Expr *e, QualType promotionType)
ImplicitParamDecl * cxxStructorImplicitParamDecl
When generating code for a constructor or destructor, this will hold the implicit argument (e....
mlir::LogicalResult emitOpenACCComputeConstruct(const OpenACCComputeConstruct &s)
EHScopeStack ehStack
Tracks function scope overall cleanup handling.
void enterDtorCleanups(const CXXDestructorDecl *dtor, CXXDtorType type)
Enter the cleanups necessary to complete the given phase of destruction for a destructor.
llvm::SmallVector< const ParmVarDecl * > fnArgs
Save Parameter Decl for coroutine.
mlir::Value emitUnPromotedValue(mlir::Value result, QualType unPromotionType)
cir::CallOp emitCoroEndBuiltinCall(mlir::Location loc, mlir::Value nullPtr)
mlir::LogicalResult emitSwitchBody(const clang::Stmt *s)
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.
void populateCatchHandlersIfRequired(cir::TryOp tryOp)
void emitNewArrayInitializer(const CXXNewExpr *e, QualType elementType, mlir::Type elementTy, Address beginPtr, mlir::Value numElements, mlir::Value allocSizeWithoutCookie)
std::optional< mlir::Value > fnRetAlloca
The compiler-generated variable that holds the return value.
void emitImplicitAssignmentOperatorBody(FunctionArgList &args)
clang::SanitizerSet sanOpts
Sanitizers enabled for this function.
RValue emitLoadOfExtVectorElementLValue(LValue lv)
mlir::Type convertTypeForMem(QualType t)
clang::QualType buildFunctionArgList(clang::GlobalDecl gd, FunctionArgList &args)
cir::CallOp emitCoroAllocBuiltinCall(mlir::Location loc)
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)
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)
void emitCXXConstructExpr(const clang::CXXConstructExpr *e, AggValueSlot dest)
mlir::Value emitLoadOfComplex(LValue src, SourceLocation loc)
Load a complex number from the specified l-value.
LValue emitAggExprToLValue(const Expr *e)
void emitStoreOfScalar(mlir::Value value, Address addr, bool isVolatile, clang::QualType ty, LValueBaseInfo baseInfo, bool isInit=false, bool isNontemporal=false)
void pushDestroy(QualType::DestructionKind dtorKind, Address addr, QualType type)
Push the standard destructor for the given type as at least a normal cleanup.
clang::CurrentSourceLocExprScope curSourceLocExprScope
Source location information about the default argument or member initializer expression we're evaluat...
mlir::Value loadCXXVTT()
Load the VTT parameter to base constructors/destructors have virtual bases.
void emitVarDecl(const clang::VarDecl &d)
This method handles emission of any variable declaration inside a function, including static vars etc...
LValue emitCompoundAssignmentLValue(const clang::CompoundAssignOperator *e)
mlir::Value emitCXXNewExpr(const CXXNewExpr *e)
RValue getUndefRValue(clang::QualType ty)
Get an appropriate 'undef' rvalue for the given type.
Address returnValue
The temporary alloca to hold the return value.
LValue makeAddrLValue(Address addr, QualType ty, LValueBaseInfo baseInfo)
mlir::LogicalResult emitLabel(const clang::LabelDecl &d)
void emitCXXConstructorCall(const clang::CXXConstructorDecl *d, clang::CXXCtorType type, bool forVirtualBase, bool delegating, AggValueSlot thisAVS, const clang::CXXConstructExpr *e)
static bool hasAggregateEvaluationKind(clang::QualType type)
mlir::Value getVTablePtr(mlir::Location loc, Address thisAddr, const clang::CXXRecordDecl *vtableClass)
Return the Value of the vtable pointer member pointed to by thisAddr.
void emitArrayDestroy(mlir::Value begin, mlir::Value numElements, QualType elementType, CharUnits elementAlign, Destroyer *destroyer)
Destroys all the elements of the given array, beginning from last to first.
RValue emitAnyExprToTemp(const clang::Expr *e)
Similarly to emitAnyExpr(), however, the result will always be accessible even if no aggregate locati...
void finishFunction(SourceLocation endLoc)
mlir::LogicalResult emitOpenACCShutdownConstruct(const OpenACCShutdownConstruct &s)
mlir::LogicalResult emitFunctionBody(const clang::Stmt *body)
mlir::LogicalResult emitBreakStmt(const clang::BreakStmt &s)
mlir::Value emitComplexPrePostIncDec(const UnaryOperator *e, LValue lv, cir::UnaryOpKind op, bool isPre)
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
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)
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)
RValue emitCall(const CIRGenFunctionInfo &funcInfo, const CIRGenCallee &callee, ReturnValueSlot returnValue, const CallArgList &args, cir::CIRCallOpInterface *callOp, mlir::Location loc)
LValue emitComplexAssignmentLValue(const BinaryOperator *e)
void emitCallArg(CallArgList &args, const clang::Expr *e, clang::QualType argType)
clang::FieldDecl * lambdaThisCaptureField
mlir::LogicalResult emitContinueStmt(const clang::ContinueStmt &s)
const clang::Decl * curCodeDecl
This is the inner-most code context, which includes blocks.
void emitConstructorBody(FunctionArgList &args)
LValue emitLValueForFieldInitialization(LValue base, const clang::FieldDecl *field, llvm::StringRef fieldName)
Like emitLValueForField, excpet that if the Field is a reference, this will return the address of the...
mlir::Value getAsNaturalPointerTo(Address addr, QualType pointeeType)
LValue emitCallExprLValue(const clang::CallExpr *e)
bool haveInsertPoint() const
True if an insertion point is defined.
llvm::SmallVector< mlir::Type, 2 > condTypeStack
The type of the condition for the emitting switch statement.
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.
void emitCXXTemporary(const CXXTemporary *temporary, QualType tempType, Address ptr)
Emits all the code to cause the given temporary to be cleaned up.
LValue emitStringLiteralLValue(const StringLiteral *e, llvm::StringRef name=".str")
void maybeEmitDeferredVarDeclInit(const VarDecl *vd)
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)
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)
mlir::LogicalResult emitIfStmt(const clang::IfStmt &s)
void emitAutoVarDecl(const clang::VarDecl &d)
Emit code and set up symbol table for a variable declaration with auto, register, or no storage class...
mlir::Value emitPromotedScalarExpr(const Expr *e, QualType promotionType)
AggValueSlot::Overlap_t getOverlapForReturnValue()
Determine whether a return value slot may overlap some other object.
cir::BrOp emitBranchThroughCleanup(mlir::Location loc, JumpDest dest)
Build a unconditional branch to the lexical scope cleanup block or with the labeled blocked if alread...
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)
CIRGenBuilderTy & getBuilder()
bool didCallStackSave
Whether a cir.stacksave operation has been added.
void emitDecl(const clang::Decl &d, bool evaluateConditionDecl=false)
LValue emitBinaryOperatorLValue(const BinaryOperator *e)
mlir::Value emitOpenACCIntExpr(const Expr *intExpr)
Address getAddrOfBitFieldStorage(LValue base, const clang::FieldDecl *field, mlir::Type fieldType, unsigned index)
AggValueSlot::Overlap_t getOverlapForBaseInit(const CXXRecordDecl *rd, const CXXRecordDecl *baseRD, bool isVirtual)
Determine whether a base class initialization may overlap some other object.
void emitDestroy(Address addr, QualType type, Destroyer *destroyer)
Immediately perform the destruction of the given object.
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.
unsigned counterRefTmp
Hold counters for incrementally naming temporaries.
mlir::MLIRContext & getMLIRContext()
mlir::LogicalResult emitOpenACCEnterDataConstruct(const OpenACCEnterDataConstruct &s)
Destroyer * getDestroyer(clang::QualType::DestructionKind kind)
void Destroyer(CIRGenFunction &cgf, Address addr, QualType ty)
void emitDestructorBody(FunctionArgList &args)
Emits the body of the current destructor.
void emitAtomicInit(Expr *init, LValue dest)
LValue emitCastLValue(const CastExpr *e)
Casts are never lvalues unless that cast is to a reference type.
mlir::Value emitLoadOfScalar(LValue lvalue, SourceLocation loc)
EmitLoadOfScalar - Load a scalar value from an address, taking care to appropriately convert from the...
mlir::LogicalResult emitCXXTryStmt(const clang::CXXTryStmt &s)
bool containsLabel(const clang::Stmt *s, bool ignoreCaseStmts=false)
Return true if the statement contains a label in it.
DeclMapTy localDeclMap
This keeps track of the CIR allocas or globals for local C declarations.
mlir::Value createOpenACCConstantInt(mlir::Location loc, unsigned width, int64_t value)
LValue emitDeclRefLValue(const clang::DeclRefExpr *e)
void emitComplexExprIntoLValue(const Expr *e, LValue dest, bool isInit)
mlir::Value emitRuntimeCall(mlir::Location loc, cir::FuncOp callee, llvm::ArrayRef< mlir::Value > args={})
llvm::DenseMap< const clang::ValueDecl *, clang::FieldDecl * > lambdaCaptureFields
RValue emitCoawaitExpr(const CoawaitExpr &e, AggValueSlot aggSlot=AggValueSlot::ignored(), bool ignoreResult=false)
ConstantEmission tryEmitAsConstant(const DeclRefExpr *refExpr)
Try to emit a reference to the given value without producing it as an l-value.
mlir::Value emitX86BuiltinExpr(unsigned builtinID, const CallExpr *e)
mlir::Value emitAlignmentAssumption(mlir::Value ptrValue, QualType ty, SourceLocation loc, SourceLocation assumptionLoc, int64_t alignment, mlir::Value offsetValue=nullptr)
mlir::LogicalResult emitCaseDefaultCascade(const T *stmt, mlir::Type condType, mlir::ArrayAttr value, cir::CaseOpKind kind, bool buildingTopLevelCase)
void emitCXXThrowExpr(const CXXThrowExpr *e)
LValue makeAddrLValue(Address addr, QualType ty, AlignmentSource source=AlignmentSource::Type)
int64_t getAccessedFieldNo(unsigned idx, mlir::ArrayAttr elts)
LValue emitPredefinedLValue(const PredefinedExpr *e)
RValue emitAnyExpr(const clang::Expr *e, AggValueSlot aggSlot=AggValueSlot::ignored(), bool ignoreResult=false)
Emit code to compute the specified expression which can have any type.
void emitCXXDestructorCall(const CXXDestructorDecl *dd, CXXDtorType type, bool forVirtualBase, bool delegating, Address thisAddr, QualType thisTy)
llvm::SmallVector< VPtr, 4 > VPtrsVector
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)
llvm::DenseMap< const OpaqueValueExpr *, RValue > opaqueRValues
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)
EHScopeStack::stable_iterator currentCleanupStackDepth
void emitCXXAggrConstructorCall(const CXXConstructorDecl *ctor, const clang::ArrayType *arrayType, Address arrayBegin, const CXXConstructExpr *e, bool newPointerIsChecked, bool zeroInitialize=false)
Emit a loop to call a particular constructor for each of several members of an array.
void pushFullExprCleanup(CleanupKind kind, As... a)
Push a cleanup to be run at the end of the current full-expression.
void emitDelegateCallArg(CallArgList &args, const clang::VarDecl *param, clang::SourceLocation loc)
We are performing a delegate call; that is, the current function is delegating to another one.
void emitAtomicStore(RValue rvalue, LValue dest, bool isInit)
mlir::Value emitStoreThroughBitfieldLValue(RValue src, LValue dstresult)
llvm::DenseMap< const OpaqueValueExpr *, LValue > opaqueLValues
Keeps track of the current set of opaque value expressions.
CIRGenFunction(CIRGenModule &cgm, CIRGenBuilderTy &builder, bool suppressNewContext=false)
void populateCatchHandlers(cir::TryOp tryOp)
std::optional< mlir::Location > currSrcLoc
Use to track source locations across nested visitor traversals.
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 emitCXXDeleteExpr(const CXXDeleteExpr *e)
mlir::LogicalResult emitCoroutineBody(const CoroutineBodyStmt &s)
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)
cir::CallOp emitCoroBeginBuiltinCall(mlir::Location loc, mlir::Value coroframeAddr)
void emitStoreThroughLValue(RValue src, LValue dst, bool isInit=false)
Store the specified rvalue into the specified lvalue, where both are guaranteed to the have the same ...
bool isLValueSuitableForInlineAtomic(LValue lv)
An LValue is a candidate for having its loads and stores be made atomic if we are operating under /vo...
mlir::LogicalResult emitStmt(const clang::Stmt *s, bool useCurrentScope, llvm::ArrayRef< const Attr * > attrs={})
void popCleanupBlocks(EHScopeStack::stable_iterator oldCleanupStackDepth)
Takes the old cleanup stack size and emits the cleanup blocks that have been added.
RValue getOrCreateOpaqueRValueMapping(const OpaqueValueExpr *e)
Given an opaque value expression, return its RValue mapping if it exists, otherwise create one.
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.
Address emitVAListRef(const Expr *e)
Build a "reference" to a va_list; this is either the address or the value of the expression,...
mlir::LogicalResult emitCompoundStmtWithoutScope(const clang::CompoundStmt &s, Address *lastValue=nullptr, AggValueSlot slot=AggValueSlot::ignored())
mlir::LogicalResult emitOpenACCExitDataConstruct(const OpenACCExitDataConstruct &s)
void 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)
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)
void popCleanupBlock()
Pops a cleanup block.
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)
Get the address of a zero-sized field within a record.
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:48
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:191
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
Contains the address where the return value of a function can be stored, and whether the address is v...
Definition CIRGenCall.h:254
Represents a call to a C++ constructor.
Definition ExprCXX.h:1548
Represents a C++ constructor within a class.
Definition DeclCXX.h:2604
Represents a C++ base or member initializer.
Definition DeclCXX.h:2369
A default argument (C++ [dcl.fct.default]).
Definition ExprCXX.h:1270
A use of a default initializer in a constructor or in aggregate initialization.
Definition ExprCXX.h:1377
Represents a delete expression for memory deallocation and destructor calls, e.g.
Definition ExprCXX.h:2626
Represents a C++ destructor within a class.
Definition DeclCXX.h:2869
A C++ dynamic_cast expression (C++ [expr.dynamic.cast]).
Definition ExprCXX.h:481
CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for statement, represented as 'for (ra...
Definition StmtCXX.h:135
Represents a call to a member function that may be written either with member call syntax (e....
Definition ExprCXX.h:179
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2129
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)".
Definition ExprCXX.h:2355
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:2745
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
Represents a C++ temporary.
Definition ExprCXX.h:1459
A C++ throw-expression (C++ [except.throw]).
Definition ExprCXX.h:1208
CXXTryStmt - A C++ try block, including all handlers.
Definition StmtCXX.h:69
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2877
CaseStmt - Represent a case statement.
Definition Stmt.h:1899
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Definition Expr.h:3610
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
Represents a 'co_await' expression.
Definition ExprCXX.h:5369
CompoundAssignOperator - For compound assignments (e.g.
Definition Expr.h:4234
CompoundLiteralExpr - [C99 6.5.2.5].
Definition Expr.h:3539
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition Stmt.h:1719
ContinueStmt - This represents a continue.
Definition Stmt.h:3098
Represents the body of a coroutine.
Definition StmtCXX.h:320
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:1270
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition Stmt.h:1610
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
DoStmt - This represents a 'do/while' stmt.
Definition Stmt.h:2811
This represents one expression.
Definition Expr.h:112
ExtVectorElementExpr - This represents access to specific elements of a vector, and may occur on the ...
Definition Expr.h:6498
Represents a member of a struct/union/class.
Definition Decl.h:3160
ForStmt - This represents a 'for (init;cond;inc)' stmt.
Definition Stmt.h:2867
Represents a function declaration or definition.
Definition Decl.h:2000
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5254
GlobalDecl - represents a global declaration.
Definition GlobalDecl.h:57
GotoStmt - This represents a direct goto.
Definition Stmt.h:2948
IfStmt - This represents an if/then/else.
Definition Stmt.h:2238
Represents the declaration of a label.
Definition Decl.h:524
LabelStmt - Represents a label, which has a substatement.
Definition Stmt.h:2125
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:3298
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
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:1178
Expr * getSourceExpr() const
The source expression of an opaque value expression is the expression which originally generated the ...
Definition Expr.h:1228
Represents a parameter to a function.
Definition Decl.h:1790
[C99 6.4.2.2] - A predefined identifier such as func.
Definition Expr.h:2005
A (possibly-)qualified type.
Definition TypeBase.h:937
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition TypeBase.h:8318
The collection of all-type qualifiers we support.
Definition TypeBase.h:331
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
Definition Stmt.h:3139
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:338
SwitchStmt - This represents a 'switch' stmt.
Definition Stmt.h:2488
Exposes information about the current target.
Definition TargetInfo.h:226
Represents a declaration of a type.
Definition Decl.h:3513
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:2244
Represents a call to the builtin function __builtin_va_arg.
Definition Expr.h:4891
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:926
Represents a C array with a specified size that is not an integer-constant-expression.
Definition TypeBase.h:3966
WhileStmt - This represents a 'while' stmt.
Definition Stmt.h:2676
#define bool
Definition gpuintrin.h:32
AlignmentSource
The source of the alignment of an l-value; an expression of confidence in the alignment actually matc...
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
@ NormalCleanup
Denotes a cleanup that should run when a scope is exited using normal control flow (falling off the e...
const internal::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.
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
#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)
Represents a scope, including function bodies, compound statements, and the substatements of if/while...
llvm::ArrayRef< mlir::Block * > getRetBlocks()
mlir::Block * createCleanupBlock(mlir::OpBuilder &builder)
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::Block * getCleanupBlock(mlir::OpBuilder &builder)
mlir::Block * getOrCreateCleanupBlock(mlir::OpBuilder &builder)
mlir::Location getRetLoc(mlir::Block *b)
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)