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
51public:
53
54private:
55 friend class ::ScalarExprEmitter;
56 /// The builder is a helper class to create IR inside a function. The
57 /// builder is stateful, in particular it keeps an "insertion point": this
58 /// is where the next operations will be introduced.
59 CIRGenBuilderTy &builder;
60
61public:
62 /// The GlobalDecl for the current function being compiled or the global
63 /// variable currently being initialized.
65
66 /// The compiler-generated variable that holds the return value.
67 std::optional<mlir::Value> fnRetAlloca;
68
69 /// The temporary alloca to hold the return value. This is
70 /// invalid iff the function has no return value.
72
73 /// Tracks function scope overall cleanup handling.
75
76 llvm::DenseMap<const clang::ValueDecl *, clang::FieldDecl *>
79
80 /// CXXThisDecl - When generating code for a C++ member function,
81 /// this will hold the implicit 'this' declaration.
83 mlir::Value cxxabiThisValue = nullptr;
84 mlir::Value cxxThisValue = nullptr;
86
87 /// When generating code for a constructor or destructor, this will hold the
88 /// implicit argument (e.g. VTT).
91
92 /// The value of 'this' to sue when evaluating CXXDefaultInitExprs within this
93 /// expression.
95
96 // Holds the Decl for the current outermost non-closure context
97 const clang::Decl *curFuncDecl = nullptr;
98 /// This is the inner-most code context, which includes blocks.
99 const clang::Decl *curCodeDecl = nullptr;
100
101 /// The function for which code is currently being generated.
102 cir::FuncOp curFn;
103
104 using DeclMapTy = llvm::DenseMap<const clang::Decl *, Address>;
105 /// This keeps track of the CIR allocas or globals for local C
106 /// declarations.
108
109 /// The type of the condition for the emitting switch statement.
111
112 clang::ASTContext &getContext() const { return cgm.getASTContext(); }
113
114 CIRGenBuilderTy &getBuilder() { return builder; }
115
117 const CIRGenModule &getCIRGenModule() const { return cgm; }
118
119 mlir::Block *getCurFunctionEntryBlock() { return &curFn.getRegion().front(); }
120
121 /// Sanitizers enabled for this function.
123
124 /// The symbol table maps a variable name to a value in the current scope.
125 /// Entering a function creates a new scope, and the function arguments are
126 /// added to the mapping. When the processing of a function is terminated,
127 /// the scope is destroyed and the mappings created in this scope are
128 /// dropped.
129 using SymTableTy = llvm::ScopedHashTable<const clang::Decl *, mlir::Value>;
131
132 /// Whether or not a Microsoft-style asm block has been processed within
133 /// this fuction. These can potentially set the return value.
134 bool sawAsmBlock = false;
135
136 mlir::Type convertTypeForMem(QualType t);
137
138 mlir::Type convertType(clang::QualType t);
139 mlir::Type convertType(const TypeDecl *t) {
140 return convertType(getContext().getTypeDeclType(t));
141 }
142
143 /// Return the cir::TypeEvaluationKind of QualType \c type.
145
149
153
155 bool suppressNewContext = false);
157
158 CIRGenTypes &getTypes() const { return cgm.getTypes(); }
159
160 const TargetInfo &getTarget() const { return cgm.getTarget(); }
161 mlir::MLIRContext &getMLIRContext() { return cgm.getMLIRContext(); }
162
163 // ---------------------
164 // Opaque value handling
165 // ---------------------
166
167 /// Keeps track of the current set of opaque value expressions.
168 llvm::DenseMap<const OpaqueValueExpr *, LValue> opaqueLValues;
169 llvm::DenseMap<const OpaqueValueExpr *, RValue> opaqueRValues;
170
171public:
172 /// A non-RAII class containing all the information about a bound
173 /// opaque value. OpaqueValueMapping, below, is a RAII wrapper for
174 /// this which makes individual mappings very simple; using this
175 /// class directly is useful when you have a variable number of
176 /// opaque values or don't want the RAII functionality for some
177 /// reason.
178 class OpaqueValueMappingData {
179 const OpaqueValueExpr *opaqueValue;
180 bool boundLValue;
181
182 OpaqueValueMappingData(const OpaqueValueExpr *ov, bool boundLValue)
183 : opaqueValue(ov), boundLValue(boundLValue) {}
184
185 public:
186 OpaqueValueMappingData() : opaqueValue(nullptr) {}
187
188 static bool shouldBindAsLValue(const Expr *expr) {
189 // gl-values should be bound as l-values for obvious reasons.
190 // Records should be bound as l-values because IR generation
191 // always keeps them in memory. Expressions of function type
192 // act exactly like l-values but are formally required to be
193 // r-values in C.
194 return expr->isGLValue() || expr->getType()->isFunctionType() ||
196 }
197
199 bind(CIRGenFunction &cgf, const OpaqueValueExpr *ov, const Expr *e) {
200 if (shouldBindAsLValue(ov))
201 return bind(cgf, ov, cgf.emitLValue(e));
202 return bind(cgf, ov, cgf.emitAnyExpr(e));
203 }
204
206 bind(CIRGenFunction &cgf, const OpaqueValueExpr *ov, const LValue &lv) {
207 assert(shouldBindAsLValue(ov));
208 cgf.opaqueLValues.insert(std::make_pair(ov, lv));
209 return OpaqueValueMappingData(ov, true);
210 }
211
213 bind(CIRGenFunction &cgf, const OpaqueValueExpr *ov, const RValue &rv) {
214 assert(!shouldBindAsLValue(ov));
215 cgf.opaqueRValues.insert(std::make_pair(ov, rv));
216
217 OpaqueValueMappingData data(ov, false);
218
219 // Work around an extremely aggressive peephole optimization in
220 // EmitScalarConversion which assumes that all other uses of a
221 // value are extant.
223 return data;
224 }
225
226 bool isValid() const { return opaqueValue != nullptr; }
227 void clear() { opaqueValue = nullptr; }
228
230 assert(opaqueValue && "no data to unbind!");
231
232 if (boundLValue) {
233 cgf.opaqueLValues.erase(opaqueValue);
234 } else {
235 cgf.opaqueRValues.erase(opaqueValue);
237 }
238 }
239 };
240
241 /// An RAII object to set (and then clear) a mapping for an OpaqueValueExpr.
243 CIRGenFunction &cgf;
245
246 public:
250
251 /// Build the opaque value mapping for the given conditional
252 /// operator if it's the GNU ?: extension. This is a common
253 /// enough pattern that the convenience operator is really
254 /// helpful.
255 ///
258 : cgf(cgf) {
259 if (mlir::isa<ConditionalOperator>(op))
260 // Leave Data empty.
261 return;
262
264 mlir::cast<BinaryConditionalOperator>(op);
266 e->getCommon());
267 }
268
269 /// Build the opaque value mapping for an OpaqueValueExpr whose source
270 /// expression is set to the expression the OVE represents.
272 : cgf(cgf) {
273 if (ov) {
274 assert(ov->getSourceExpr() && "wrong form of OpaqueValueMapping used "
275 "for OVE with no source expression");
276 data = OpaqueValueMappingData::bind(cgf, ov, ov->getSourceExpr());
277 }
278 }
279
281 LValue lvalue)
282 : cgf(cgf),
283 data(OpaqueValueMappingData::bind(cgf, opaqueValue, lvalue)) {}
284
286 RValue rvalue)
287 : cgf(cgf),
288 data(OpaqueValueMappingData::bind(cgf, opaqueValue, rvalue)) {}
289
290 void pop() {
291 data.unbind(cgf);
292 data.clear();
293 }
294
296 if (data.isValid())
297 data.unbind(cgf);
298 }
299 };
300
301private:
302 /// Declare a variable in the current scope, return success if the variable
303 /// wasn't declared yet.
304 void declare(mlir::Value addrVal, const clang::Decl *var, clang::QualType ty,
305 mlir::Location loc, clang::CharUnits alignment,
306 bool isParam = false);
307
308public:
309 mlir::Value createDummyValue(mlir::Location loc, clang::QualType qt);
310
311 void emitNullInitialization(mlir::Location loc, Address destPtr, QualType ty);
312
313private:
314 // Track current variable initialization (if there's one)
315 const clang::VarDecl *currVarDecl = nullptr;
316 class VarDeclContext {
318 const clang::VarDecl *oldVal = nullptr;
319
320 public:
321 VarDeclContext(CIRGenFunction &p, const VarDecl *value) : p(p) {
322 if (p.currVarDecl)
323 oldVal = p.currVarDecl;
324 p.currVarDecl = value;
325 }
326
327 /// Can be used to restore the state early, before the dtor
328 /// is run.
329 void restore() { p.currVarDecl = oldVal; }
330 ~VarDeclContext() { restore(); }
331 };
332
333public:
334 /// Use to track source locations across nested visitor traversals.
335 /// Always use a `SourceLocRAIIObject` to change currSrcLoc.
336 std::optional<mlir::Location> currSrcLoc;
338 CIRGenFunction &cgf;
339 std::optional<mlir::Location> oldLoc;
340
341 public:
342 SourceLocRAIIObject(CIRGenFunction &cgf, mlir::Location value) : cgf(cgf) {
343 if (cgf.currSrcLoc)
344 oldLoc = cgf.currSrcLoc;
345 cgf.currSrcLoc = value;
346 }
347
348 /// Can be used to restore the state early, before the dtor
349 /// is run.
350 void restore() { cgf.currSrcLoc = oldLoc; }
352 };
353
355 llvm::ScopedHashTableScope<const clang::Decl *, mlir::Value>;
356
357 /// Hold counters for incrementally naming temporaries
358 unsigned counterRefTmp = 0;
359 unsigned counterAggTmp = 0;
360 std::string getCounterRefTmpAsString();
361 std::string getCounterAggTmpAsString();
362
363 /// Helpers to convert Clang's SourceLocation to a MLIR Location.
364 mlir::Location getLoc(clang::SourceLocation srcLoc);
365 mlir::Location getLoc(clang::SourceRange srcLoc);
366 mlir::Location getLoc(mlir::Location lhs, mlir::Location rhs);
367
368 const clang::LangOptions &getLangOpts() const { return cgm.getLangOpts(); }
369
370 /// True if an insertion point is defined. If not, this indicates that the
371 /// current code being emitted is unreachable.
372 /// FIXME(cir): we need to inspect this and perhaps use a cleaner mechanism
373 /// since we don't yet force null insertion point to designate behavior (like
374 /// LLVM's codegen does) and we probably shouldn't.
375 bool haveInsertPoint() const {
376 return builder.getInsertionBlock() != nullptr;
377 }
378
379 // Wrapper for function prototype sources. Wraps either a FunctionProtoType or
380 // an ObjCMethodDecl.
382 llvm::PointerUnion<const clang::FunctionProtoType *,
383 const clang::ObjCMethodDecl *>
385
388 };
389
391
392 /// An abstract representation of regular/ObjC call/message targets.
394 /// The function declaration of the callee.
395 [[maybe_unused]] const clang::Decl *calleeDecl;
396
397 public:
398 AbstractCallee() : calleeDecl(nullptr) {}
399 AbstractCallee(const clang::FunctionDecl *fd) : calleeDecl(fd) {}
400
401 bool hasFunctionDecl() const {
402 return llvm::isa_and_nonnull<clang::FunctionDecl>(calleeDecl);
403 }
404
405 unsigned getNumParams() const {
406 if (const auto *fd = llvm::dyn_cast<clang::FunctionDecl>(calleeDecl))
407 return fd->getNumParams();
408 return llvm::cast<clang::ObjCMethodDecl>(calleeDecl)->param_size();
409 }
410
411 const clang::ParmVarDecl *getParamDecl(unsigned I) const {
412 if (const auto *fd = llvm::dyn_cast<clang::FunctionDecl>(calleeDecl))
413 return fd->getParamDecl(I);
414 return *(llvm::cast<clang::ObjCMethodDecl>(calleeDecl)->param_begin() +
415 I);
416 }
417 };
418
419 void finishFunction(SourceLocation endLoc);
420
421 /// Determine whether the given initializer is trivial in the sense
422 /// that it requires no code to be generated.
423 bool isTrivialInitializer(const Expr *init);
424
425 /// If the specified expression does not fold to a constant, or if it does but
426 /// contains a label, return false. If it constant folds return true and set
427 /// the boolean result in Result.
428 bool constantFoldsToBool(const clang::Expr *cond, bool &resultBool,
429 bool allowLabels = false);
431 llvm::APSInt &resultInt,
432 bool allowLabels = false);
433
434 /// Return true if the statement contains a label in it. If
435 /// this statement is not executed normally, it not containing a label means
436 /// that we can just remove the code.
437 bool containsLabel(const clang::Stmt *s, bool ignoreCaseStmts = false);
438
439 class ConstantEmission {
440 // Cannot use mlir::TypedAttr directly here because of bit availability.
441 llvm::PointerIntPair<mlir::Attribute, 1, bool> valueAndIsReference;
442 ConstantEmission(mlir::TypedAttr c, bool isReference)
443 : valueAndIsReference(c, isReference) {}
444
445 public:
447 static ConstantEmission forReference(mlir::TypedAttr c) {
448 return ConstantEmission(c, true);
449 }
450 static ConstantEmission forValue(mlir::TypedAttr c) {
451 return ConstantEmission(c, false);
452 }
453
454 explicit operator bool() const {
455 return valueAndIsReference.getOpaqueValue() != nullptr;
456 }
457
458 bool isReference() const { return valueAndIsReference.getInt(); }
460 assert(isReference());
461 cgf.cgm.errorNYI(refExpr->getSourceRange(),
462 "ConstantEmission::getReferenceLValue");
463 return {};
464 }
465
466 mlir::TypedAttr getValue() const {
467 assert(!isReference());
468 return mlir::cast<mlir::TypedAttr>(valueAndIsReference.getPointer());
469 }
470 };
471
472 ConstantEmission tryEmitAsConstant(const DeclRefExpr *refExpr);
473 ConstantEmission tryEmitAsConstant(const MemberExpr *me);
474
477 /// The address of the alloca for languages with explicit address space
478 /// (e.g. OpenCL) or alloca casted to generic pointer for address space
479 /// agnostic languages (e.g. C++). Invalid if the variable was emitted
480 /// as a global constant.
482
483 /// True if the variable is of aggregate type and has a constant
484 /// initializer.
486
487 /// True if the variable is a __block variable that is captured by an
488 /// escaping block.
489 bool IsEscapingByRef = false;
490
491 /// True if the variable was emitted as an offload recipe, and thus doesn't
492 /// have the same sort of alloca initialization.
493 bool EmittedAsOffload = false;
494
495 mlir::Value NRVOFlag{};
496
497 struct Invalid {};
499
501 : Variable(&variable), Addr(Address::invalid()) {}
502
504
505 bool wasEmittedAsGlobal() const { return !Addr.isValid(); }
506
508
509 /// Returns the raw, allocated address, which is not necessarily
510 /// the address of the object itself. It is casted to default
511 /// address space for address space agnostic languages.
512 Address getAllocatedAddress() const { return Addr; }
513
514 // Changes the stored address for the emission. This function should only
515 // be used in extreme cases, and isn't required to model normal AST
516 // initialization/variables.
518
519 /// Returns the address of the object within this declaration.
520 /// Note that this does not chase the forwarding pointer for
521 /// __block decls.
523 if (!IsEscapingByRef)
524 return Addr;
525
527 return Address::invalid();
528 }
529 };
530
531 /// Perform the usual unary conversions on the specified expression and
532 /// compare the result against zero, returning an Int1Ty value.
533 mlir::Value evaluateExprAsBool(const clang::Expr *e);
534
535 cir::GlobalOp addInitializerToStaticVarDecl(const VarDecl &d,
536 cir::GlobalOp gv,
537 cir::GetGlobalOp gvAddr);
538
539 /// Set the address of a local variable.
541 assert(!localDeclMap.count(vd) && "Decl already exists in LocalDeclMap!");
542 localDeclMap.insert({vd, addr});
543
544 // Add to the symbol table if not there already.
545 if (symbolTable.count(vd))
546 return;
547 symbolTable.insert(vd, addr.getPointer());
548 }
549
550 // A class to allow reverting changes to a var-decl's registration to the
551 // localDeclMap. This is used in cases where things are being inserted into
552 // the variable list but don't follow normal lookup/search rules, like in
553 // OpenACC recipe generation.
555 CIRGenFunction &cgf;
556 const VarDecl *vd;
557 bool shouldDelete = false;
558 Address oldAddr = Address::invalid();
559
560 public:
562 : cgf(cgf), vd(vd) {
563 auto mapItr = cgf.localDeclMap.find(vd);
564
565 if (mapItr != cgf.localDeclMap.end())
566 oldAddr = mapItr->second;
567 else
568 shouldDelete = true;
569 }
570
572 if (shouldDelete)
573 cgf.localDeclMap.erase(vd);
574 else
575 cgf.localDeclMap.insert_or_assign(vd, oldAddr);
576 }
577 };
578
580
583
584 static bool
586
593
596
600 const clang::CXXRecordDecl *nearestVBase,
601 clang::CharUnits offsetFromNearestVBase,
602 bool baseIsNonVirtualPrimaryBase,
603 const clang::CXXRecordDecl *vtableClass,
604 VisitedVirtualBasesSetTy &vbases, VPtrsVector &vptrs);
605 /// Return the Value of the vtable pointer member pointed to by thisAddr.
606 mlir::Value getVTablePtr(mlir::Location loc, Address thisAddr,
607 const clang::CXXRecordDecl *vtableClass);
608
609 /// Returns whether we should perform a type checked load when loading a
610 /// virtual function for virtual calls to members of RD. This is generally
611 /// true when both vcall CFI and whole-program-vtables are enabled.
613
614 /// Source location information about the default argument or member
615 /// initializer expression we're evaluating, if any.
619
620 /// A scope within which we are constructing the fields of an object which
621 /// might use a CXXDefaultInitExpr. This stashes away a 'this' value to use if
622 /// we need to evaluate the CXXDefaultInitExpr within the evaluation.
624 public:
626 : cgf(cgf), oldCXXDefaultInitExprThis(cgf.cxxDefaultInitExprThis) {
627 cgf.cxxDefaultInitExprThis = thisAddr;
628 }
630 cgf.cxxDefaultInitExprThis = oldCXXDefaultInitExprThis;
631 }
632
633 private:
634 CIRGenFunction &cgf;
635 Address oldCXXDefaultInitExprThis;
636 };
637
638 /// The scope of a CXXDefaultInitExpr. Within this scope, the value of 'this'
639 /// is overridden to be the object under construction.
641 public:
646 cgf.cxxThisValue = cgf.cxxDefaultInitExprThis.getPointer();
647 cgf.cxxThisAlignment = cgf.cxxDefaultInitExprThis.getAlignment();
648 }
650 cgf.cxxThisValue = oldCXXThisValue;
651 cgf.cxxThisAlignment = oldCXXThisAlignment;
652 }
653
654 public:
656 mlir::Value oldCXXThisValue;
659 };
660
662 LValue makeNaturalAlignAddrLValue(mlir::Value val, QualType ty);
663
664 /// Construct an address with the natural alignment of T. If a pointer to T
665 /// is expected to be signed, the pointer passed to this function must have
666 /// been signed, and the returned Address will have the pointer authentication
667 /// information needed to authenticate the signed pointer.
669 CharUnits alignment,
670 bool forPointeeType = false,
671 LValueBaseInfo *baseInfo = nullptr) {
672 if (alignment.isZero())
673 alignment = cgm.getNaturalTypeAlignment(t, baseInfo);
674 return Address(ptr, convertTypeForMem(t), alignment);
675 }
676
678 Address value, const CXXRecordDecl *derived,
679 llvm::iterator_range<CastExpr::path_const_iterator> path,
680 bool nullCheckValue, SourceLocation loc);
681
682 /// Return the VTT parameter that should be passed to a base
683 /// constructor/destructor with virtual bases.
684 /// FIXME: VTTs are Itanium ABI-specific, so the definition should move
685 /// to ItaniumCXXABI.cpp together with all the references to VTT.
686 mlir::Value getVTTParameter(GlobalDecl gd, bool forVirtualBase,
687 bool delegating);
688
691 return makeAddrLValue(addr, ty, LValueBaseInfo(source));
692 }
693
695 return LValue::makeAddr(addr, ty, baseInfo);
696 }
697
698 void initializeVTablePointers(mlir::Location loc,
699 const clang::CXXRecordDecl *rd);
700 void initializeVTablePointer(mlir::Location loc, const VPtr &vptr);
701
703
704 /// Return the address of a local variable.
706 auto it = localDeclMap.find(vd);
707 assert(it != localDeclMap.end() &&
708 "Invalid argument to getAddrOfLocalVar(), no decl!");
709 return it->second;
710 }
711
713 mlir::Type fieldType, unsigned index);
714
715 /// Given an opaque value expression, return its LValue mapping if it exists,
716 /// otherwise create one.
718
719 /// Given an opaque value expression, return its RValue mapping if it exists,
720 /// otherwise create one.
722
723 /// Load the value for 'this'. This function is only valid while generating
724 /// code for an C++ member function.
725 /// FIXME(cir): this should return a mlir::Value!
726 mlir::Value loadCXXThis() {
727 assert(cxxThisValue && "no 'this' value for this function");
728 return cxxThisValue;
729 }
731
732 /// Load the VTT parameter to base constructors/destructors have virtual
733 /// bases. FIXME: Every place that calls LoadCXXVTT is something that needs to
734 /// be abstracted properly.
735 mlir::Value loadCXXVTT() {
736 assert(cxxStructorImplicitParamValue && "no VTT value for this function");
738 }
739
740 /// Convert the given pointer to a complete class to the given direct base.
742 Address value,
743 const CXXRecordDecl *derived,
744 const CXXRecordDecl *base,
745 bool baseIsVirtual);
746
747 /// Determine whether a return value slot may overlap some other object.
749 // FIXME: Assuming no overlap here breaks guaranteed copy elision for base
750 // class subobjects. These cases may need to be revisited depending on the
751 // resolution of the relevant core issue.
753 }
754
755 /// Determine whether a base class initialization may overlap some other
756 /// object.
758 const CXXRecordDecl *baseRD,
759 bool isVirtual);
760
761 /// Get an appropriate 'undef' rvalue for the given type.
762 /// TODO: What's the equivalent for MLIR? Currently we're only using this for
763 /// void types so it just returns RValue::get(nullptr) but it'll need
764 /// addressed later.
766
767 cir::FuncOp generateCode(clang::GlobalDecl gd, cir::FuncOp fn,
768 cir::FuncType funcType);
769
771 FunctionArgList &args);
772
773 /// Emit code for the start of a function.
774 /// \param loc The location to be associated with the function.
775 /// \param startLoc The location of the function body.
777 cir::FuncOp fn, cir::FuncType funcType,
779 clang::SourceLocation startLoc);
780
781 /// The cleanup depth enclosing all the cleanups associated with the
782 /// parameters.
784
785 /// Takes the old cleanup stack size and emits the cleanup blocks
786 /// that have been added.
787 void popCleanupBlocks(EHScopeStack::stable_iterator oldCleanupStackDepth);
788 void popCleanupBlock();
789
790 /// Push a cleanup to be run at the end of the current full-expression. Safe
791 /// against the possibility that we're currently inside a
792 /// conditionally-evaluated expression.
793 template <class T, class... As>
794 void pushFullExprCleanup(CleanupKind kind, As... a) {
795 // If we're not in a conditional branch, or if none of the
796 // arguments requires saving, then use the unconditional cleanup.
798 return ehStack.pushCleanup<T>(kind, a...);
799
800 cgm.errorNYI("pushFullExprCleanup in conditional branch");
801 }
802
803 /// Enters a new scope for capturing cleanups, all of which
804 /// will be executed once the scope is exited.
805 class RunCleanupsScope {
806 EHScopeStack::stable_iterator cleanupStackDepth, oldCleanupStackDepth;
807
808 protected:
810
811 private:
812 RunCleanupsScope(const RunCleanupsScope &) = delete;
813 void operator=(const RunCleanupsScope &) = delete;
814
815 protected:
817
818 public:
819 /// Enter a new cleanup scope.
822 cleanupStackDepth = cgf.ehStack.stable_begin();
823 oldCleanupStackDepth = cgf.currentCleanupStackDepth;
824 cgf.currentCleanupStackDepth = cleanupStackDepth;
825 }
826
827 /// Exit this cleanup scope, emitting any accumulated cleanups.
832
833 /// Force the emission of cleanups now, instead of waiting
834 /// until this object is destroyed.
836 assert(performCleanup && "Already forced cleanup");
837 {
838 mlir::OpBuilder::InsertionGuard guard(cgf.getBuilder());
839 cgf.popCleanupBlocks(cleanupStackDepth);
840 performCleanup = false;
841 cgf.currentCleanupStackDepth = oldCleanupStackDepth;
842 }
843 }
844 };
845
846 // Cleanup stack depth of the RunCleanupsScope that was pushed most recently.
848
849public:
850 /// Represents a scope, including function bodies, compound statements, and
851 /// the substatements of if/while/do/for/switch/try statements. This class
852 /// handles any automatic cleanup, along with the return value.
853 struct LexicalScope : public RunCleanupsScope {
854 private:
855 // Block containing cleanup code for things initialized in this
856 // lexical context (scope).
857 mlir::Block *cleanupBlock = nullptr;
858
859 // Points to the scope entry block. This is useful, for instance, for
860 // helping to insert allocas before finalizing any recursive CodeGen from
861 // switches.
862 mlir::Block *entryBlock;
863
864 LexicalScope *parentScope = nullptr;
865
866 // Only Regular is used at the moment. Support for other kinds will be
867 // added as the relevant statements/expressions are upstreamed.
868 enum Kind {
869 Regular, // cir.if, cir.scope, if_regions
870 Ternary, // cir.ternary
871 Switch, // cir.switch
872 Try, // cir.try
873 GlobalInit // cir.global initialization code
874 };
875 Kind scopeKind = Kind::Regular;
876
877 // The scope return value.
878 mlir::Value retVal = nullptr;
879
880 mlir::Location beginLoc;
881 mlir::Location endLoc;
882
883 public:
884 unsigned depth = 0;
885
886 LexicalScope(CIRGenFunction &cgf, mlir::Location loc, mlir::Block *eb)
887 : RunCleanupsScope(cgf), entryBlock(eb), parentScope(cgf.curLexScope),
888 beginLoc(loc), endLoc(loc) {
889
890 assert(entryBlock && "LexicalScope requires an entry block");
891 cgf.curLexScope = this;
892 if (parentScope)
893 ++depth;
894
895 if (const auto fusedLoc = mlir::dyn_cast<mlir::FusedLoc>(loc)) {
896 assert(fusedLoc.getLocations().size() == 2 && "too many locations");
897 beginLoc = fusedLoc.getLocations()[0];
898 endLoc = fusedLoc.getLocations()[1];
899 }
900 }
901
902 void setRetVal(mlir::Value v) { retVal = v; }
903
904 void cleanup();
905 void restore() { cgf.curLexScope = parentScope; }
906
912
913 // ---
914 // Kind
915 // ---
916 bool isGlobalInit() { return scopeKind == Kind::GlobalInit; }
917 bool isRegular() { return scopeKind == Kind::Regular; }
918 bool isSwitch() { return scopeKind == Kind::Switch; }
919 bool isTernary() { return scopeKind == Kind::Ternary; }
920 bool isTry() { return scopeKind == Kind::Try; }
921
922 void setAsGlobalInit() { scopeKind = Kind::GlobalInit; }
923 void setAsSwitch() { scopeKind = Kind::Switch; }
924 void setAsTernary() { scopeKind = Kind::Ternary; }
925
926 // Lazy create cleanup block or return what's available.
927 mlir::Block *getOrCreateCleanupBlock(mlir::OpBuilder &builder) {
928 if (cleanupBlock)
929 return cleanupBlock;
930 cleanupBlock = createCleanupBlock(builder);
931 return cleanupBlock;
932 }
933
934 mlir::Block *getCleanupBlock(mlir::OpBuilder &builder) {
935 return cleanupBlock;
936 }
937
938 mlir::Block *createCleanupBlock(mlir::OpBuilder &builder) {
939 // Create the cleanup block but dont hook it up around just yet.
940 mlir::OpBuilder::InsertionGuard guard(builder);
941 mlir::Region *r = builder.getBlock() ? builder.getBlock()->getParent()
942 : &cgf.curFn->getRegion(0);
943 cleanupBlock = builder.createBlock(r);
944 return cleanupBlock;
945 }
946
947 // ---
948 // Return handling.
949 // ---
950
951 private:
952 // `returnBlock`, `returnLoc`, and all the functions that deal with them
953 // will change and become more complicated when `switch` statements are
954 // upstreamed. `case` statements within the `switch` are in the same scope
955 // but have their own regions. Therefore the LexicalScope will need to
956 // keep track of multiple return blocks.
957 mlir::Block *returnBlock = nullptr;
958 std::optional<mlir::Location> returnLoc;
959
960 // See the comment on `getOrCreateRetBlock`.
961 mlir::Block *createRetBlock(CIRGenFunction &cgf, mlir::Location loc) {
962 assert(returnBlock == nullptr && "only one return block per scope");
963 // Create the cleanup block but don't hook it up just yet.
964 mlir::OpBuilder::InsertionGuard guard(cgf.builder);
965 returnBlock =
966 cgf.builder.createBlock(cgf.builder.getBlock()->getParent());
967 updateRetLoc(returnBlock, loc);
968 return returnBlock;
969 }
970
971 cir::ReturnOp emitReturn(mlir::Location loc);
972 void emitImplicitReturn();
973
974 public:
975 mlir::Block *getRetBlock() { return returnBlock; }
976 mlir::Location getRetLoc(mlir::Block *b) { return *returnLoc; }
977 void updateRetLoc(mlir::Block *b, mlir::Location loc) { returnLoc = loc; }
978
979 // Create the return block for this scope, or return the existing one.
980 // This get-or-create logic is necessary to handle multiple return
981 // statements within the same scope, which can happen if some of them are
982 // dead code or if there is a `goto` into the middle of the scope.
983 mlir::Block *getOrCreateRetBlock(CIRGenFunction &cgf, mlir::Location loc) {
984 if (returnBlock == nullptr) {
985 returnBlock = createRetBlock(cgf, loc);
986 return returnBlock;
987 }
988 updateRetLoc(returnBlock, loc);
989 return returnBlock;
990 }
991
992 mlir::Block *getEntryBlock() { return entryBlock; }
993 };
994
996
997 typedef void Destroyer(CIRGenFunction &cgf, Address addr, QualType ty);
998
1000
1001 void pushDestroy(CleanupKind kind, Address addr, QualType type,
1002 Destroyer *destroyer);
1003
1005
1006 /// ----------------------
1007 /// CIR emit functions
1008 /// ----------------------
1009public:
1010 mlir::Value emitAlignmentAssumption(mlir::Value ptrValue, QualType ty,
1011 SourceLocation loc,
1012 SourceLocation assumptionLoc,
1013 int64_t alignment,
1014 mlir::Value offsetValue = nullptr);
1015
1016 mlir::Value emitAlignmentAssumption(mlir::Value ptrValue, const Expr *expr,
1017 SourceLocation assumptionLoc,
1018 int64_t alignment,
1019 mlir::Value offsetValue = nullptr);
1020
1021private:
1022 void emitAndUpdateRetAlloca(clang::QualType type, mlir::Location loc,
1023 clang::CharUnits alignment);
1024
1025 CIRGenCallee emitDirectCallee(const GlobalDecl &gd);
1026
1027public:
1029 llvm::StringRef fieldName,
1030 unsigned fieldIndex);
1031
1032 mlir::Value emitAlloca(llvm::StringRef name, mlir::Type ty,
1033 mlir::Location loc, clang::CharUnits alignment,
1034 bool insertIntoFnEntryBlock,
1035 mlir::Value arraySize = nullptr);
1036 mlir::Value emitAlloca(llvm::StringRef name, mlir::Type ty,
1037 mlir::Location loc, clang::CharUnits alignment,
1038 mlir::OpBuilder::InsertPoint ip,
1039 mlir::Value arraySize = nullptr);
1040
1041 void emitAggregateStore(mlir::Value value, Address dest);
1042
1043 void emitAggExpr(const clang::Expr *e, AggValueSlot slot);
1044
1046
1047 /// Emit an aggregate copy.
1048 ///
1049 /// \param isVolatile \c true iff either the source or the destination is
1050 /// volatile.
1051 /// \param MayOverlap Whether the tail padding of the destination might be
1052 /// occupied by some other object. More efficient code can often be
1053 /// generated if not.
1054 void emitAggregateCopy(LValue dest, LValue src, QualType eltTy,
1055 AggValueSlot::Overlap_t mayOverlap);
1056
1057 /// Emit code to compute the specified expression which can have any type. The
1058 /// result is returned as an RValue struct. If this is an aggregate
1059 /// expression, the aggloc/agglocvolatile arguments indicate where the result
1060 /// should be returned.
1063
1064 /// Emits the code necessary to evaluate an arbitrary expression into the
1065 /// given memory location.
1066 void emitAnyExprToMem(const Expr *e, Address location, Qualifiers quals,
1067 bool isInitializer);
1068
1069 /// Similarly to emitAnyExpr(), however, the result will always be accessible
1070 /// even if no aggregate location is provided.
1072
1073 void emitArrayDestroy(mlir::Value begin, mlir::Value numElements,
1074 QualType elementType, CharUnits elementAlign,
1075 Destroyer *destroyer);
1076
1077 mlir::Value emitArrayLength(const clang::ArrayType *arrayType,
1078 QualType &baseType, Address &addr);
1080
1082 LValueBaseInfo *baseInfo = nullptr);
1083
1084 mlir::LogicalResult emitAsmStmt(const clang::AsmStmt &s);
1085
1087 void emitAtomicInit(Expr *init, LValue dest);
1088
1090 mlir::OpBuilder::InsertPoint ip = {});
1091
1092 /// Emit code and set up symbol table for a variable declaration with auto,
1093 /// register, or no storage class specifier. These turn into simple stack
1094 /// objects, globals depending on target.
1095 void emitAutoVarDecl(const clang::VarDecl &d);
1096
1097 void emitAutoVarCleanups(const AutoVarEmission &emission);
1098 /// Emit the initializer for an allocated variable. If this call is not
1099 /// associated with the call to emitAutoVarAlloca (as the address of the
1100 /// emission is not directly an alloca), the allocatedSeparately parameter can
1101 /// be used to suppress the assertions. However, this should only be used in
1102 /// extreme cases, as it doesn't properly reflect the language/AST.
1103 void emitAutoVarInit(const AutoVarEmission &emission);
1104 void emitAutoVarTypeCleanup(const AutoVarEmission &emission,
1106
1107 void maybeEmitDeferredVarDeclInit(const VarDecl *vd);
1108
1109 void emitBaseInitializer(mlir::Location loc, const CXXRecordDecl *classDecl,
1110 CXXCtorInitializer *baseInit);
1111
1113
1114 mlir::LogicalResult emitBreakStmt(const clang::BreakStmt &s);
1115
1116 RValue emitBuiltinExpr(const clang::GlobalDecl &gd, unsigned builtinID,
1118
1119 RValue emitCall(const CIRGenFunctionInfo &funcInfo,
1121 const CallArgList &args, cir::CIRCallOpInterface *callOp,
1122 mlir::Location loc);
1125 const CallArgList &args,
1126 cir::CIRCallOpInterface *callOrTryCall = nullptr) {
1127 assert(currSrcLoc && "source location must have been set");
1128 return emitCall(funcInfo, callee, returnValue, args, callOrTryCall,
1129 *currSrcLoc);
1130 }
1131
1132 RValue emitCall(clang::QualType calleeTy, const CIRGenCallee &callee,
1134 void emitCallArg(CallArgList &args, const clang::Expr *e,
1135 clang::QualType argType);
1136 void emitCallArgs(
1137 CallArgList &args, PrototypeWrapper prototype,
1138 llvm::iterator_range<clang::CallExpr::const_arg_iterator> argRange,
1139 AbstractCallee callee = AbstractCallee(), unsigned paramsToSkip = 0);
1144
1145 template <typename T>
1146 mlir::LogicalResult emitCaseDefaultCascade(const T *stmt, mlir::Type condType,
1147 mlir::ArrayAttr value,
1148 cir::CaseOpKind kind,
1149 bool buildingTopLevelCase);
1150
1151 mlir::LogicalResult emitCaseStmt(const clang::CaseStmt &s,
1152 mlir::Type condType,
1153 bool buildingTopLevelCase);
1154
1155 LValue emitCastLValue(const CastExpr *e);
1156
1157 /// Emits an argument for a call to a `__builtin_assume`. If the builtin
1158 /// sanitizer is enabled, a runtime check is also emitted.
1159 mlir::Value emitCheckedArgForAssume(const Expr *e);
1160
1161 /// Emit a conversion from the specified complex type to the specified
1162 /// destination type, where the destination type is an LLVM scalar type.
1163 mlir::Value emitComplexToScalarConversion(mlir::Value src, QualType srcTy,
1164 QualType dstTy, SourceLocation loc);
1165
1168
1170
1171 void emitDestroy(Address addr, QualType type, Destroyer *destroyer);
1172
1174
1175 mlir::LogicalResult emitContinueStmt(const clang::ContinueStmt &s);
1176
1178 AggValueSlot dest);
1179
1182 Address arrayBegin, const CXXConstructExpr *e,
1183 bool newPointerIsChecked,
1184 bool zeroInitialize = false);
1186 mlir::Value numElements, Address arrayBase,
1187 const CXXConstructExpr *e,
1188 bool newPointerIsChecked,
1189 bool zeroInitialize);
1191 clang::CXXCtorType type, bool forVirtualBase,
1192 bool delegating, AggValueSlot thisAVS,
1193 const clang::CXXConstructExpr *e);
1194
1196 clang::CXXCtorType type, bool forVirtualBase,
1197 bool delegating, Address thisAddr,
1199
1201 bool forVirtualBase, bool delegating,
1202 Address thisAddr, QualType thisTy);
1203
1205 mlir::Value thisVal, QualType thisTy,
1206 mlir::Value implicitParam,
1207 QualType implicitParamTy, const CallExpr *e);
1208
1209 mlir::LogicalResult emitCXXForRangeStmt(const CXXForRangeStmt &s,
1211
1214
1216 const clang::CXXMethodDecl *md, const CIRGenCallee &callee,
1217 ReturnValueSlot returnValue, mlir::Value thisPtr,
1218 mlir::Value implicitParam, clang::QualType implicitParamTy,
1219 const clang::CallExpr *ce, CallArgList *rtlArgs);
1220
1222 const clang::CallExpr *ce, const clang::CXXMethodDecl *md,
1223 ReturnValueSlot returnValue, bool hasQualifier,
1224 clang::NestedNameSpecifier qualifier, bool isArrow,
1225 const clang::Expr *base);
1226
1227 mlir::Value emitCXXNewExpr(const CXXNewExpr *e);
1228
1230 const CXXMethodDecl *md,
1232
1234
1235 void emitCXXThrowExpr(const CXXThrowExpr *e);
1236
1238 clang::CXXCtorType ctorType, FunctionArgList &args);
1239
1240 // It's important not to confuse this and emitDelegateCXXConstructorCall.
1241 // Delegating constructors are the C++11 feature. The constructor delegate
1242 // optimization is used to reduce duplication in the base and complete
1243 // constructors where they are substantially the same.
1245 const FunctionArgList &args);
1246
1247 mlir::LogicalResult emitDoStmt(const clang::DoStmt &s);
1248
1249 /// Emit an expression as an initializer for an object (variable, field, etc.)
1250 /// at the given location. The expression is not necessarily the normal
1251 /// initializer for the object, and the address is not necessarily
1252 /// its normal location.
1253 ///
1254 /// \param init the initializing expression
1255 /// \param d the object to act as if we're initializing
1256 /// \param lvalue the lvalue to initialize
1257 /// \param capturedByInit true if \p d is a __block variable whose address is
1258 /// potentially changed by the initializer
1259 void emitExprAsInit(const clang::Expr *init, const clang::ValueDecl *d,
1260 LValue lvalue, bool capturedByInit = false);
1261
1262 mlir::LogicalResult emitFunctionBody(const clang::Stmt *body);
1263
1264 mlir::LogicalResult emitGotoStmt(const clang::GotoStmt &s);
1265
1267
1269 clang::Expr *init);
1270
1271 mlir::Value emitPromotedComplexExpr(const Expr *e, QualType promotionType);
1272
1273 mlir::Value emitPromotedScalarExpr(const Expr *e, QualType promotionType);
1274
1275 mlir::Value emitPromotedValue(mlir::Value result, QualType promotionType);
1276
1277 void emitReturnOfRValue(mlir::Location loc, RValue rv, QualType ty);
1278
1279 /// Emit the computation of the specified expression of scalar type.
1280 mlir::Value emitScalarExpr(const clang::Expr *e);
1281
1282 mlir::Value emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv,
1283 cir::UnaryOpKind kind, bool isPre);
1284
1285 /// Build a debug stoppoint if we are emitting debug info.
1286 void emitStopPoint(const Stmt *s);
1287
1288 // Build CIR for a statement. useCurrentScope should be true if no
1289 // new scopes need be created when finding a compound statement.
1290 mlir::LogicalResult emitStmt(const clang::Stmt *s, bool useCurrentScope,
1291 llvm::ArrayRef<const Attr *> attrs = {});
1292
1293 mlir::LogicalResult emitSimpleStmt(const clang::Stmt *s,
1294 bool useCurrentScope);
1295
1296 mlir::LogicalResult emitForStmt(const clang::ForStmt &s);
1297
1298 void emitForwardingCallToLambda(const CXXMethodDecl *lambdaCallOperator,
1299 CallArgList &callArgs);
1300
1301 /// Emit the computation of the specified expression of complex type,
1302 /// returning the result.
1303 mlir::Value emitComplexExpr(const Expr *e);
1304
1305 void emitComplexExprIntoLValue(const Expr *e, LValue dest, bool isInit);
1306
1307 mlir::Value emitComplexPrePostIncDec(const UnaryOperator *e, LValue lv,
1308 cir::UnaryOpKind op, bool isPre);
1309
1313 mlir::Value &result);
1314
1315 mlir::LogicalResult
1316 emitCompoundStmt(const clang::CompoundStmt &s, Address *lastValue = nullptr,
1318
1319 mlir::LogicalResult
1321 Address *lastValue = nullptr,
1323
1324 void emitDecl(const clang::Decl &d, bool evaluateConditionDecl = false);
1325 mlir::LogicalResult emitDeclStmt(const clang::DeclStmt &s);
1327
1328 mlir::LogicalResult emitDefaultStmt(const clang::DefaultStmt &s,
1329 mlir::Type condType,
1330 bool buildingTopLevelCase);
1331
1333 clang::CXXCtorType ctorType,
1334 const FunctionArgList &args,
1336
1337 /// We are performing a delegate call; that is, the current function is
1338 /// delegating to another one. Produce a r-value suitable for passing the
1339 /// given parameter.
1340 void emitDelegateCallArg(CallArgList &args, const clang::VarDecl *param,
1342
1343 /// Emit an `if` on a boolean condition to the specified blocks.
1344 /// FIXME: Based on the condition, this might try to simplify the codegen of
1345 /// the conditional based on the branch.
1346 /// In the future, we may apply code generation simplifications here,
1347 /// similar to those used in classic LLVM codegen
1348 /// See `EmitBranchOnBoolExpr` for inspiration.
1349 mlir::LogicalResult emitIfOnBoolExpr(const clang::Expr *cond,
1350 const clang::Stmt *thenS,
1351 const clang::Stmt *elseS);
1352 cir::IfOp emitIfOnBoolExpr(const clang::Expr *cond,
1353 BuilderCallbackRef thenBuilder,
1354 mlir::Location thenLoc,
1355 BuilderCallbackRef elseBuilder,
1356 std::optional<mlir::Location> elseLoc = {});
1357
1358 mlir::Value emitOpOnBoolExpr(mlir::Location loc, const clang::Expr *cond);
1359
1360 mlir::LogicalResult emitLabel(const clang::LabelDecl &d);
1361 mlir::LogicalResult emitLabelStmt(const clang::LabelStmt &s);
1362
1365
1366 mlir::LogicalResult emitIfStmt(const clang::IfStmt &s);
1367
1368 /// Emit code to compute the specified expression,
1369 /// ignoring the result.
1370 void emitIgnoredExpr(const clang::Expr *e);
1371
1372 RValue emitLoadOfBitfieldLValue(LValue lv, SourceLocation loc);
1373
1374 /// Load a complex number from the specified l-value.
1375 mlir::Value emitLoadOfComplex(LValue src, SourceLocation loc);
1376
1377 /// Given an expression that represents a value lvalue, this method emits
1378 /// the address of the lvalue, then loads the result as an rvalue,
1379 /// returning the rvalue.
1380 RValue emitLoadOfLValue(LValue lv, SourceLocation loc);
1381
1382 Address emitLoadOfReference(LValue refLVal, mlir::Location loc,
1383 LValueBaseInfo *pointeeBaseInfo);
1384 LValue emitLoadOfReferenceLValue(Address refAddr, mlir::Location loc,
1385 QualType refTy, AlignmentSource source);
1386
1387 /// EmitLoadOfScalar - Load a scalar value from an address, taking
1388 /// care to appropriately convert from the memory representation to
1389 /// the LLVM value representation. The l-value must be a simple
1390 /// l-value.
1391 mlir::Value emitLoadOfScalar(LValue lvalue, SourceLocation loc);
1392 mlir::Value emitLoadOfScalar(Address addr, bool isVolatile, QualType ty,
1393 SourceLocation loc, LValueBaseInfo baseInfo);
1394
1395 /// Emit code to compute a designator that specifies the location
1396 /// of the expression.
1397 /// FIXME: document this function better.
1398 LValue emitLValue(const clang::Expr *e);
1399 LValue emitLValueForBitField(LValue base, const FieldDecl *field);
1400 LValue emitLValueForField(LValue base, const clang::FieldDecl *field);
1401
1402 LValue emitLValueForLambdaField(const FieldDecl *field);
1403 LValue emitLValueForLambdaField(const FieldDecl *field,
1404 mlir::Value thisValue);
1405
1406 /// Like emitLValueForField, excpet that if the Field is a reference, this
1407 /// will return the address of the reference and not the address of the value
1408 /// stored in the reference.
1409 LValue emitLValueForFieldInitialization(LValue base,
1410 const clang::FieldDecl *field,
1411 llvm::StringRef fieldName);
1412
1414
1415 LValue emitMemberExpr(const MemberExpr *e);
1416
1417 /// Given an expression with a pointer type, emit the value and compute our
1418 /// best estimate of the alignment of the pointee.
1419 ///
1420 /// One reasonable way to use this information is when there's a language
1421 /// guarantee that the pointer must be aligned to some stricter value, and
1422 /// we're simply trying to ensure that sufficiently obvious uses of under-
1423 /// aligned objects don't get miscompiled; for example, a placement new
1424 /// into the address of a local variable. In such a case, it's quite
1425 /// reasonable to just ignore the returned alignment when it isn't from an
1426 /// explicit source.
1428 LValueBaseInfo *baseInfo = nullptr);
1429
1430 /// Emits a reference binding to the passed in expression.
1431 RValue emitReferenceBindingToExpr(const Expr *e);
1432
1433 mlir::LogicalResult emitReturnStmt(const clang::ReturnStmt &s);
1434
1435 RValue emitRotate(const CallExpr *e, bool isRotateLeft);
1436
1437 mlir::Value emitScalarConstant(const ConstantEmission &constant, Expr *e);
1438
1439 /// Emit a conversion from the specified type to the specified destination
1440 /// type, both of which are CIR scalar types.
1441 mlir::Value emitScalarConversion(mlir::Value src, clang::QualType srcType,
1442 clang::QualType dstType,
1444
1445 void emitScalarInit(const clang::Expr *init, mlir::Location loc,
1446 LValue lvalue, bool capturedByInit = false);
1447
1448 void emitStaticVarDecl(const VarDecl &d, cir::GlobalLinkageKind linkage);
1449
1450 void emitStoreOfComplex(mlir::Location loc, mlir::Value v, LValue dest,
1451 bool isInit);
1452
1453 void emitStoreOfScalar(mlir::Value value, Address addr, bool isVolatile,
1454 clang::QualType ty, bool isInit = false,
1455 bool isNontemporal = false);
1456 void emitStoreOfScalar(mlir::Value value, LValue lvalue, bool isInit);
1457
1458 /// Store the specified rvalue into the specified
1459 /// lvalue, where both are guaranteed to the have the same type, and that type
1460 /// is 'Ty'.
1461 void emitStoreThroughLValue(RValue src, LValue dst, bool isInit = false);
1462
1463 mlir::Value emitStoreThroughBitfieldLValue(RValue src, LValue dstresult);
1464
1465 LValue emitStringLiteralLValue(const StringLiteral *e);
1466
1467 mlir::LogicalResult emitSwitchBody(const clang::Stmt *s);
1468 mlir::LogicalResult emitSwitchCase(const clang::SwitchCase &s,
1469 bool buildingTopLevelCase);
1470 mlir::LogicalResult emitSwitchStmt(const clang::SwitchStmt &s);
1471
1472 /// Given a value and its clang type, returns the value casted to its memory
1473 /// representation.
1474 /// Note: CIR defers most of the special casting to the final lowering passes
1475 /// to conserve the high level information.
1476 mlir::Value emitToMemory(mlir::Value value, clang::QualType ty);
1477
1478 /// Emit a trap instruction, which is used to abort the program in an abnormal
1479 /// way, usually for debugging purposes.
1480 /// \p createNewBlock indicates whether to create a new block for the IR
1481 /// builder. Since the `cir.trap` operation is a terminator, operations that
1482 /// follow a trap cannot be emitted after `cir.trap` in the same block. To
1483 /// ensure these operations get emitted successfully, you need to create a new
1484 /// dummy block and set the insertion point there before continuing from the
1485 /// trap operation.
1486 void emitTrap(mlir::Location loc, bool createNewBlock);
1487
1488 LValue emitUnaryOpLValue(const clang::UnaryOperator *e);
1489
1490 mlir::Value emitUnPromotedValue(mlir::Value result, QualType unPromotionType);
1491
1492 /// Emit a reached-unreachable diagnostic if \p loc is valid and runtime
1493 /// checking is enabled. Otherwise, just emit an unreachable instruction.
1494 /// \p createNewBlock indicates whether to create a new block for the IR
1495 /// builder. Since the `cir.unreachable` operation is a terminator, operations
1496 /// that follow an unreachable point cannot be emitted after `cir.unreachable`
1497 /// in the same block. To ensure these operations get emitted successfully,
1498 /// you need to create a dummy block and set the insertion point there before
1499 /// continuing from the unreachable point.
1500 void emitUnreachable(clang::SourceLocation loc, bool createNewBlock);
1501
1502 /// This method handles emission of any variable declaration
1503 /// inside a function, including static vars etc.
1504 void emitVarDecl(const clang::VarDecl &d);
1505
1507
1508 mlir::LogicalResult emitWhileStmt(const clang::WhileStmt &s);
1509
1510 /// Given an assignment `*lhs = rhs`, emit a test that checks if \p rhs is
1511 /// nonnull, if 1\p LHS is marked _Nonnull.
1512 void emitNullabilityCheck(LValue lhs, mlir::Value rhs,
1514
1515 /// An object to manage conditionally-evaluated expressions.
1517 CIRGenFunction &cgf;
1518 mlir::OpBuilder::InsertPoint insertPt;
1519
1520 public:
1522 : cgf(cgf), insertPt(cgf.builder.saveInsertionPoint()) {}
1523 ConditionalEvaluation(CIRGenFunction &cgf, mlir::OpBuilder::InsertPoint ip)
1524 : cgf(cgf), insertPt(ip) {}
1525
1527 assert(cgf.outermostConditional != this);
1528 if (!cgf.outermostConditional)
1529 cgf.outermostConditional = this;
1530 }
1531
1533 assert(cgf.outermostConditional != nullptr);
1534 if (cgf.outermostConditional == this)
1535 cgf.outermostConditional = nullptr;
1536 }
1537
1538 /// Returns the insertion point which will be executed prior to each
1539 /// evaluation of the conditional code. In LLVM OG, this method
1540 /// is called getStartingBlock.
1541 mlir::OpBuilder::InsertPoint getInsertPoint() const { return insertPt; }
1542 };
1543
1545 std::optional<LValue> lhs{}, rhs{};
1546 mlir::Value result{};
1547 };
1548
1549 // Return true if we're currently emitting one branch or the other of a
1550 // conditional expression.
1551 bool isInConditionalBranch() const { return outermostConditional != nullptr; }
1552
1553 void setBeforeOutermostConditional(mlir::Value value, Address addr) {
1554 assert(isInConditionalBranch());
1555 {
1556 mlir::OpBuilder::InsertionGuard guard(builder);
1557 builder.restoreInsertionPoint(outermostConditional->getInsertPoint());
1558 builder.createStore(
1559 value.getLoc(), value, addr, /*isVolatile=*/false,
1560 mlir::IntegerAttr::get(
1561 mlir::IntegerType::get(value.getContext(), 64),
1562 (uint64_t)addr.getAlignment().getAsAlign().value()));
1563 }
1564 }
1565
1566 // Points to the outermost active conditional control. This is used so that
1567 // we know if a temporary should be destroyed conditionally.
1569
1570 /// An RAII object to record that we're evaluating a statement
1571 /// expression.
1573 CIRGenFunction &cgf;
1574
1575 /// We have to save the outermost conditional: cleanups in a
1576 /// statement expression aren't conditional just because the
1577 /// StmtExpr is.
1578 ConditionalEvaluation *savedOutermostConditional;
1579
1580 public:
1582 : cgf(cgf), savedOutermostConditional(cgf.outermostConditional) {
1583 cgf.outermostConditional = nullptr;
1584 }
1585
1587 cgf.outermostConditional = savedOutermostConditional;
1588 }
1589 };
1590
1591 template <typename FuncTy>
1593 const FuncTy &branchGenFunc);
1594
1595 mlir::Value emitTernaryOnBoolExpr(const clang::Expr *cond, mlir::Location loc,
1596 const clang::Stmt *thenS,
1597 const clang::Stmt *elseS);
1598
1599 /// Build a "reference" to a va_list; this is either the address or the value
1600 /// of the expression, depending on how va_list is defined.
1601 Address emitVAListRef(const Expr *e);
1602
1603 /// Emits the start of a CIR variable-argument operation (`cir.va_start`)
1604 ///
1605 /// \param vaList A reference to the \c va_list as emitted by either
1606 /// \c emitVAListRef or \c emitMSVAListRef.
1607 ///
1608 /// \param count The number of arguments in \c vaList
1609 void emitVAStart(mlir::Value vaList, mlir::Value count);
1610
1611 /// Emits the end of a CIR variable-argument operation (`cir.va_start`)
1612 ///
1613 /// \param vaList A reference to the \c va_list as emitted by either
1614 /// \c emitVAListRef or \c emitMSVAListRef.
1615 void emitVAEnd(mlir::Value vaList);
1616
1617 /// Generate code to get an argument from the passed in pointer
1618 /// and update it accordingly.
1619 ///
1620 /// \param ve The \c VAArgExpr for which to generate code.
1621 ///
1622 /// \param vaListAddr Receives a reference to the \c va_list as emitted by
1623 /// either \c emitVAListRef or \c emitMSVAListRef.
1624 ///
1625 /// \returns SSA value with the argument.
1626 mlir::Value emitVAArg(VAArgExpr *ve);
1627
1628 /// ----------------------
1629 /// CIR build helpers
1630 /// -----------------
1631public:
1632 cir::AllocaOp createTempAlloca(mlir::Type ty, mlir::Location loc,
1633 const Twine &name = "tmp",
1634 mlir::Value arraySize = nullptr,
1635 bool insertIntoFnEntryBlock = false);
1636 cir::AllocaOp createTempAlloca(mlir::Type ty, mlir::Location loc,
1637 const Twine &name = "tmp",
1638 mlir::OpBuilder::InsertPoint ip = {},
1639 mlir::Value arraySize = nullptr);
1640 Address createTempAlloca(mlir::Type ty, CharUnits align, mlir::Location loc,
1641 const Twine &name = "tmp",
1642 mlir::Value arraySize = nullptr,
1643 Address *alloca = nullptr,
1644 mlir::OpBuilder::InsertPoint ip = {});
1645 Address createTempAllocaWithoutCast(mlir::Type ty, CharUnits align,
1646 mlir::Location loc,
1647 const Twine &name = "tmp",
1648 mlir::Value arraySize = nullptr,
1649 mlir::OpBuilder::InsertPoint ip = {});
1650
1651 /// Create a temporary memory object of the given type, with
1652 /// appropriate alignmen and cast it to the default address space. Returns
1653 /// the original alloca instruction by \p Alloca if it is not nullptr.
1654 Address createMemTemp(QualType t, mlir::Location loc,
1655 const Twine &name = "tmp", Address *alloca = nullptr,
1656 mlir::OpBuilder::InsertPoint ip = {});
1657 Address createMemTemp(QualType t, CharUnits align, mlir::Location loc,
1658 const Twine &name = "tmp", Address *alloca = nullptr,
1659 mlir::OpBuilder::InsertPoint ip = {});
1660
1661 //===--------------------------------------------------------------------===//
1662 // OpenACC Emission
1663 //===--------------------------------------------------------------------===//
1664private:
1665 template <typename Op>
1666 Op emitOpenACCOp(mlir::Location start, OpenACCDirectiveKind dirKind,
1667 SourceLocation dirLoc,
1668 llvm::ArrayRef<const OpenACCClause *> clauses);
1669 // Function to do the basic implementation of an operation with an Associated
1670 // Statement. Models AssociatedStmtConstruct.
1671 template <typename Op, typename TermOp>
1672 mlir::LogicalResult emitOpenACCOpAssociatedStmt(
1673 mlir::Location start, mlir::Location end, OpenACCDirectiveKind dirKind,
1674 SourceLocation dirLoc, llvm::ArrayRef<const OpenACCClause *> clauses,
1675 const Stmt *associatedStmt);
1676
1677 template <typename Op, typename TermOp>
1678 mlir::LogicalResult emitOpenACCOpCombinedConstruct(
1679 mlir::Location start, mlir::Location end, OpenACCDirectiveKind dirKind,
1680 SourceLocation dirLoc, llvm::ArrayRef<const OpenACCClause *> clauses,
1681 const Stmt *loopStmt);
1682
1683 template <typename Op>
1684 void emitOpenACCClauses(Op &op, OpenACCDirectiveKind dirKind,
1685 SourceLocation dirLoc,
1686 ArrayRef<const OpenACCClause *> clauses);
1687 // The second template argument doesn't need to be a template, since it should
1688 // always be an mlir::acc::LoopOp, but as this is a template anyway, we make
1689 // it a template argument as this way we can avoid including the OpenACC MLIR
1690 // headers here. We will count on linker failures/explicit instantiation to
1691 // ensure we don't mess this up, but it is only called from 1 place, and
1692 // instantiated 3x.
1693 template <typename ComputeOp, typename LoopOp>
1694 void emitOpenACCClauses(ComputeOp &op, LoopOp &loopOp,
1695 OpenACCDirectiveKind dirKind, SourceLocation dirLoc,
1696 ArrayRef<const OpenACCClause *> clauses);
1697
1698 // The OpenACC LoopOp requires that we have auto, seq, or independent on all
1699 // LoopOp operations for the 'none' device type case. This function checks if
1700 // the LoopOp has one, else it updates it to have one.
1701 void updateLoopOpParallelism(mlir::acc::LoopOp &op, bool isOrphan,
1703
1704 // The OpenACC 'cache' construct actually applies to the 'loop' if present. So
1705 // keep track of the 'loop' so that we can add the cache vars to it correctly.
1706 mlir::acc::LoopOp *activeLoopOp = nullptr;
1707
1708 struct ActiveOpenACCLoopRAII {
1709 CIRGenFunction &cgf;
1710 mlir::acc::LoopOp *oldLoopOp;
1711
1712 ActiveOpenACCLoopRAII(CIRGenFunction &cgf, mlir::acc::LoopOp *newOp)
1713 : cgf(cgf), oldLoopOp(cgf.activeLoopOp) {
1714 cgf.activeLoopOp = newOp;
1715 }
1716 ~ActiveOpenACCLoopRAII() { cgf.activeLoopOp = oldLoopOp; }
1717 };
1718
1719public:
1720 // Helper type used to store the list of important information for a 'data'
1721 // clause variable, or a 'cache' variable reference.
1729 // Gets the collection of info required to lower and OpenACC clause or cache
1730 // construct variable reference.
1732 // Helper function to emit the integer expressions as required by an OpenACC
1733 // clause/construct.
1734 mlir::Value emitOpenACCIntExpr(const Expr *intExpr);
1735 // Helper function to emit an integer constant as an mlir int type, used for
1736 // constants in OpenACC constructs/clauses.
1737 mlir::Value createOpenACCConstantInt(mlir::Location loc, unsigned width,
1738 int64_t value);
1739
1740 mlir::LogicalResult
1742 mlir::LogicalResult emitOpenACCLoopConstruct(const OpenACCLoopConstruct &s);
1743 mlir::LogicalResult
1745 mlir::LogicalResult emitOpenACCDataConstruct(const OpenACCDataConstruct &s);
1746 mlir::LogicalResult
1748 mlir::LogicalResult
1750 mlir::LogicalResult
1752 mlir::LogicalResult emitOpenACCWaitConstruct(const OpenACCWaitConstruct &s);
1753 mlir::LogicalResult emitOpenACCInitConstruct(const OpenACCInitConstruct &s);
1754 mlir::LogicalResult
1756 mlir::LogicalResult emitOpenACCSetConstruct(const OpenACCSetConstruct &s);
1757 mlir::LogicalResult
1759 mlir::LogicalResult
1761 mlir::LogicalResult emitOpenACCCacheConstruct(const OpenACCCacheConstruct &s);
1762
1765
1766 /// Create a temporary memory object for the given aggregate type.
1767 AggValueSlot createAggTemp(QualType ty, mlir::Location loc,
1768 const Twine &name = "tmp",
1769 Address *alloca = nullptr) {
1771 return AggValueSlot::forAddr(
1772 createMemTemp(ty, loc, name, alloca), ty.getQualifiers(),
1775 }
1776
1777private:
1778 QualType getVarArgType(const Expr *arg);
1779};
1780
1781} // namespace clang::CIRGen
1782
1783#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
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:188
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:3720
AsmStmt is the base class for GCCAsmStmt and MSAsmStmt.
Definition Stmt.h:3236
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:3135
mlir::Value getPointer() const
Definition Address.h:81
static Address invalid()
Definition Address.h:66
clang::CharUnits getAlignment() const
Definition Address.h:109
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,...
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.
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()
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.
LValue emitScalarCompoundAssignWithComplex(const CompoundAssignOperator *e, mlir::Value &result)
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 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())
LValue emitMemberExpr(const MemberExpr *e)
clang::CharUnits cxxThisAlignment
const TargetInfo & getTarget() const
llvm::DenseMap< const clang::Decl *, Address > DeclMapTy
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.
LValue makeNaturalAlignAddrLValue(mlir::Value val, QualType ty)
bool constantFoldsToSimpleInteger(const clang::Expr *cond, llvm::APSInt &resultInt, bool allowLabels=false)
If the specified expression does not fold to a constant, or if it does fold but contains a label,...
void emitStoreOfScalar(mlir::Value value, Address addr, bool isVolatile, clang::QualType ty, bool isInit=false, bool isNontemporal=false)
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)
LValue emitStringLiteralLValue(const StringLiteral *e)
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::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)
RValue emitAnyExpr(const clang::Expr *e, AggValueSlot aggSlot=AggValueSlot::ignored())
Emit code to compute the specified expression which can have any type.
mlir::LogicalResult emitSwitchStmt(const clang::SwitchStmt &s)
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)
AggValueSlot::Overlap_t getOverlapForFieldInit(const FieldDecl *fd)
mlir::LogicalResult emitSimpleStmt(const clang::Stmt *s, bool useCurrentScope)
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...
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.
mlir::Value emitUnPromotedValue(mlir::Value result, QualType unPromotionType)
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.
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.
mlir::Type convertTypeForMem(QualType t)
clang::QualType buildFunctionArgList(clang::GlobalDecl gd, FunctionArgList &args)
ConditionalInfo emitConditionalBlocks(const AbstractConditionalOperator *e, const FuncTy &branchGenFunc)
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)
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...
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...
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.
mlir::Value emitScalarExpr(const clang::Expr *e)
Emit the computation of the specified expression of scalar type.
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 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::LogicalResult emitIfStmt(const clang::IfStmt &s)
void emitAutoVarDecl(const clang::VarDecl &d)
Emit code and set up symbol table for a variable declaration with auto, register, or no storage class...
cir::FuncOp curFn
The function for which code is currently being generated.
void pushDestroy(CleanupKind kind, Address addr, QualType type, Destroyer *destroyer)
mlir::Value emitPromotedScalarExpr(const Expr *e, QualType promotionType)
AggValueSlot::Overlap_t getOverlapForReturnValue()
Determine whether a return value slot may overlap some other object.
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()
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...
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)
llvm::DenseMap< const clang::ValueDecl *, clang::FieldDecl * > lambdaCaptureFields
ConstantEmission tryEmitAsConstant(const DeclRefExpr *refExpr)
Try to emit a reference to the given value without producing it as an l-value.
mlir::Value emitAlignmentAssumption(mlir::Value ptrValue, QualType ty, SourceLocation loc, SourceLocation assumptionLoc, int64_t alignment, mlir::Value offsetValue=nullptr)
mlir::LogicalResult emitCaseDefaultCascade(const T *stmt, mlir::Type condType, mlir::ArrayAttr value, cir::CaseOpKind kind, bool buildingTopLevelCase)
void emitCXXThrowExpr(const CXXThrowExpr *e)
LValue makeAddrLValue(Address addr, QualType ty, AlignmentSource source=AlignmentSource::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.
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)
std::optional< mlir::Location > currSrcLoc
Use to track source locations across nested visitor traversals.
LValue emitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *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 emitAggregateCopy(LValue dest, LValue src, QualType eltTy, AggValueSlot::Overlap_t mayOverlap)
Emit an aggregate copy.
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)
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)
void emitAggExpr(const clang::Expr *e, AggValueSlot slot)
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:252
Represents a call to a C++ constructor.
Definition ExprCXX.h:1549
Represents a C++ constructor within a class.
Definition DeclCXX.h:2604
Represents a C++ base or member initializer.
Definition DeclCXX.h:2369
A use of a default initializer in a constructor or in aggregate initialization.
Definition ExprCXX.h:1378
Represents a C++ destructor within a class.
Definition DeclCXX.h:2869
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:2349
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:2739
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
A C++ throw-expression (C++ [except.throw]).
Definition ExprCXX.h:1209
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:1920
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
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:1720
ContinueStmt - This represents a continue.
Definition Stmt.h:3119
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:1611
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
DoStmt - This represents a 'do/while' stmt.
Definition Stmt.h:2832
This represents one expression.
Definition Expr.h:112
Represents a member of a struct/union/class.
Definition Decl.h:3157
ForStmt - This represents a 'for (init;cond;inc)' stmt.
Definition Stmt.h:2888
Represents a function declaration or definition.
Definition Decl.h:1999
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5264
GlobalDecl - represents a global declaration.
Definition GlobalDecl.h:57
GotoStmt - This represents a direct goto.
Definition Stmt.h:2969
IfStmt - This represents an if/then/else.
Definition Stmt.h:2259
Represents the declaration of a label.
Definition Decl.h:523
LabelStmt - Represents a label, which has a substatement.
Definition Stmt.h:2146
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Represents a prvalue temporary that is written into memory so that a reference can bind to it.
Definition ExprCXX.h:4914
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:1789
A (possibly-)qualified type.
Definition TypeBase.h:937
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition TypeBase.h:8325
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:3160
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:334
StringLiteral - This represents a string literal expression, e.g.
Definition Expr.h:1799
SwitchStmt - This represents a 'switch' stmt.
Definition Stmt.h:2509
Exposes information about the current target.
Definition TargetInfo.h:226
Represents a declaration of a type.
Definition Decl.h:3510
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:711
Represents a variable declaration or definition.
Definition Decl.h:925
WhileStmt - This represents a 'while' stmt.
Definition Stmt.h:2697
#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.
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 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.
bool EmittedAsOffload
True if the variable was emitted as an offload recipe, and thus doesn't have the same sort of alloca ...
Address Addr
The address of the alloca for languages with explicit address space (e.g.
bool IsConstantAggregate
True if the variable is of aggregate type and has a constant initializer.
Represents a scope, including function bodies, compound statements, and the substatements of if/while...
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