clang 22.0.0git
CIRGenFunction.h
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Internal per-function state used for AST-to-ClangIR code gen
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef CLANG_LIB_CIR_CODEGEN_CIRGENFUNCTION_H
14#define CLANG_LIB_CIR_CODEGEN_CIRGENFUNCTION_H
15
16#include "CIRGenBuilder.h"
17#include "CIRGenCall.h"
18#include "CIRGenModule.h"
19#include "CIRGenTypeCache.h"
20#include "CIRGenValue.h"
21#include "EHScopeStack.h"
22
23#include "Address.h"
24
27#include "clang/AST/CharUnits.h"
29#include "clang/AST/Decl.h"
30#include "clang/AST/ExprCXX.h"
31#include "clang/AST/Stmt.h"
32#include "clang/AST/Type.h"
36#include "llvm/ADT/ScopedHashTable.h"
37
38namespace {
39class ScalarExprEmitter;
40} // namespace
41
42namespace mlir {
43namespace acc {
44class LoopOp;
45} // namespace acc
46} // namespace mlir
47
48namespace clang::CIRGen {
49
50struct CGCoroData;
51
53public:
55
56private:
57 friend class ::ScalarExprEmitter;
58 /// The builder is a helper class to create IR inside a function. The
59 /// builder is stateful, in particular it keeps an "insertion point": this
60 /// is where the next operations will be introduced.
61 CIRGenBuilderTy &builder;
62
63public:
64 /// The GlobalDecl for the current function being compiled or the global
65 /// variable currently being initialized.
67
68 /// The compiler-generated variable that holds the return value.
69 std::optional<mlir::Value> fnRetAlloca;
70
71 // Holds coroutine data if the current function is a coroutine. We use a
72 // wrapper to manage its lifetime, so that we don't have to define CGCoroData
73 // in this header.
74 struct CGCoroInfo {
75 std::unique_ptr<CGCoroData> data;
76 CGCoroInfo();
78 };
80
81 bool isCoroutine() const { return curCoro.data != nullptr; }
82
83 /// The temporary alloca to hold the return value. This is
84 /// invalid iff the function has no return value.
86
87 /// Tracks function scope overall cleanup handling.
89
90 llvm::DenseMap<const clang::ValueDecl *, clang::FieldDecl *>
93
94 /// CXXThisDecl - When generating code for a C++ member function,
95 /// this will hold the implicit 'this' declaration.
97 mlir::Value cxxabiThisValue = nullptr;
98 mlir::Value cxxThisValue = nullptr;
100
101 /// When generating code for a constructor or destructor, this will hold the
102 /// implicit argument (e.g. VTT).
105
106 /// The value of 'this' to sue when evaluating CXXDefaultInitExprs within this
107 /// expression.
109
110 // Holds the Decl for the current outermost non-closure context
111 const clang::Decl *curFuncDecl = nullptr;
112 /// This is the inner-most code context, which includes blocks.
113 const clang::Decl *curCodeDecl = nullptr;
114
115 /// The current function or global initializer that is generated code for.
116 /// This is usually a cir::FuncOp, but it can also be a cir::GlobalOp for
117 /// global initializers.
118 mlir::Operation *curFn = nullptr;
119
120 using DeclMapTy = llvm::DenseMap<const clang::Decl *, Address>;
121 /// This keeps track of the CIR allocas or globals for local C
122 /// declarations.
124
125 /// The type of the condition for the emitting switch statement.
127
128 clang::ASTContext &getContext() const { return cgm.getASTContext(); }
129
130 CIRGenBuilderTy &getBuilder() { return builder; }
131
133 const CIRGenModule &getCIRGenModule() const { return cgm; }
134
136 // We currently assume this isn't called for a global initializer.
137 auto fn = mlir::cast<cir::FuncOp>(curFn);
138 return &fn.getRegion().front();
139 }
140
141 /// Sanitizers enabled for this function.
143
144 /// The symbol table maps a variable name to a value in the current scope.
145 /// Entering a function creates a new scope, and the function arguments are
146 /// added to the mapping. When the processing of a function is terminated,
147 /// the scope is destroyed and the mappings created in this scope are
148 /// dropped.
149 using SymTableTy = llvm::ScopedHashTable<const clang::Decl *, mlir::Value>;
151
152 /// Whether or not a Microsoft-style asm block has been processed within
153 /// this fuction. These can potentially set the return value.
154 bool sawAsmBlock = false;
155
156 mlir::Type convertTypeForMem(QualType t);
157
158 mlir::Type convertType(clang::QualType t);
159 mlir::Type convertType(const TypeDecl *t) {
160 return convertType(getContext().getTypeDeclType(t));
161 }
162
163 /// Return the cir::TypeEvaluationKind of QualType \c type.
165
169
173
175 bool suppressNewContext = false);
177
178 CIRGenTypes &getTypes() const { return cgm.getTypes(); }
179
180 const TargetInfo &getTarget() const { return cgm.getTarget(); }
181 mlir::MLIRContext &getMLIRContext() { return cgm.getMLIRContext(); }
182
183 // ---------------------
184 // Opaque value handling
185 // ---------------------
186
187 /// Keeps track of the current set of opaque value expressions.
188 llvm::DenseMap<const OpaqueValueExpr *, LValue> opaqueLValues;
189 llvm::DenseMap<const OpaqueValueExpr *, RValue> opaqueRValues;
190
191public:
192 /// A non-RAII class containing all the information about a bound
193 /// opaque value. OpaqueValueMapping, below, is a RAII wrapper for
194 /// this which makes individual mappings very simple; using this
195 /// class directly is useful when you have a variable number of
196 /// opaque values or don't want the RAII functionality for some
197 /// reason.
198 class OpaqueValueMappingData {
199 const OpaqueValueExpr *opaqueValue;
200 bool boundLValue;
201
202 OpaqueValueMappingData(const OpaqueValueExpr *ov, bool boundLValue)
203 : opaqueValue(ov), boundLValue(boundLValue) {}
204
205 public:
206 OpaqueValueMappingData() : opaqueValue(nullptr) {}
207
208 static bool shouldBindAsLValue(const Expr *expr) {
209 // gl-values should be bound as l-values for obvious reasons.
210 // Records should be bound as l-values because IR generation
211 // always keeps them in memory. Expressions of function type
212 // act exactly like l-values but are formally required to be
213 // r-values in C.
214 return expr->isGLValue() || expr->getType()->isFunctionType() ||
216 }
217
219 bind(CIRGenFunction &cgf, const OpaqueValueExpr *ov, const Expr *e) {
220 if (shouldBindAsLValue(ov))
221 return bind(cgf, ov, cgf.emitLValue(e));
222 return bind(cgf, ov, cgf.emitAnyExpr(e));
223 }
224
226 bind(CIRGenFunction &cgf, const OpaqueValueExpr *ov, const LValue &lv) {
227 assert(shouldBindAsLValue(ov));
228 cgf.opaqueLValues.insert(std::make_pair(ov, lv));
229 return OpaqueValueMappingData(ov, true);
230 }
231
233 bind(CIRGenFunction &cgf, const OpaqueValueExpr *ov, const RValue &rv) {
234 assert(!shouldBindAsLValue(ov));
235 cgf.opaqueRValues.insert(std::make_pair(ov, rv));
236
237 OpaqueValueMappingData data(ov, false);
238
239 // Work around an extremely aggressive peephole optimization in
240 // EmitScalarConversion which assumes that all other uses of a
241 // value are extant.
243 return data;
244 }
245
246 bool isValid() const { return opaqueValue != nullptr; }
247 void clear() { opaqueValue = nullptr; }
248
250 assert(opaqueValue && "no data to unbind!");
251
252 if (boundLValue) {
253 cgf.opaqueLValues.erase(opaqueValue);
254 } else {
255 cgf.opaqueRValues.erase(opaqueValue);
257 }
258 }
259 };
260
261 /// An RAII object to set (and then clear) a mapping for an OpaqueValueExpr.
263 CIRGenFunction &cgf;
265
266 public:
270
271 /// Build the opaque value mapping for the given conditional
272 /// operator if it's the GNU ?: extension. This is a common
273 /// enough pattern that the convenience operator is really
274 /// helpful.
275 ///
278 : cgf(cgf) {
279 if (mlir::isa<ConditionalOperator>(op))
280 // Leave Data empty.
281 return;
282
284 mlir::cast<BinaryConditionalOperator>(op);
286 e->getCommon());
287 }
288
289 /// Build the opaque value mapping for an OpaqueValueExpr whose source
290 /// expression is set to the expression the OVE represents.
292 : cgf(cgf) {
293 if (ov) {
294 assert(ov->getSourceExpr() && "wrong form of OpaqueValueMapping used "
295 "for OVE with no source expression");
296 data = OpaqueValueMappingData::bind(cgf, ov, ov->getSourceExpr());
297 }
298 }
299
301 LValue lvalue)
302 : cgf(cgf),
303 data(OpaqueValueMappingData::bind(cgf, opaqueValue, lvalue)) {}
304
306 RValue rvalue)
307 : cgf(cgf),
308 data(OpaqueValueMappingData::bind(cgf, opaqueValue, rvalue)) {}
309
310 void pop() {
311 data.unbind(cgf);
312 data.clear();
313 }
314
316 if (data.isValid())
317 data.unbind(cgf);
318 }
319 };
320
321private:
322 /// Declare a variable in the current scope, return success if the variable
323 /// wasn't declared yet.
324 void declare(mlir::Value addrVal, const clang::Decl *var, clang::QualType ty,
325 mlir::Location loc, clang::CharUnits alignment,
326 bool isParam = false);
327
328public:
329 mlir::Value createDummyValue(mlir::Location loc, clang::QualType qt);
330
331 void emitNullInitialization(mlir::Location loc, Address destPtr, QualType ty);
332
333private:
334 // Track current variable initialization (if there's one)
335 const clang::VarDecl *currVarDecl = nullptr;
336 class VarDeclContext {
338 const clang::VarDecl *oldVal = nullptr;
339
340 public:
341 VarDeclContext(CIRGenFunction &p, const VarDecl *value) : p(p) {
342 if (p.currVarDecl)
343 oldVal = p.currVarDecl;
344 p.currVarDecl = value;
345 }
346
347 /// Can be used to restore the state early, before the dtor
348 /// is run.
349 void restore() { p.currVarDecl = oldVal; }
350 ~VarDeclContext() { restore(); }
351 };
352
353public:
354 /// Use to track source locations across nested visitor traversals.
355 /// Always use a `SourceLocRAIIObject` to change currSrcLoc.
356 std::optional<mlir::Location> currSrcLoc;
358 CIRGenFunction &cgf;
359 std::optional<mlir::Location> oldLoc;
360
361 public:
362 SourceLocRAIIObject(CIRGenFunction &cgf, mlir::Location value) : cgf(cgf) {
363 if (cgf.currSrcLoc)
364 oldLoc = cgf.currSrcLoc;
365 cgf.currSrcLoc = value;
366 }
367
368 /// Can be used to restore the state early, before the dtor
369 /// is run.
370 void restore() { cgf.currSrcLoc = oldLoc; }
372 };
373
375 llvm::ScopedHashTableScope<const clang::Decl *, mlir::Value>;
376
377 /// Hold counters for incrementally naming temporaries
378 unsigned counterRefTmp = 0;
379 unsigned counterAggTmp = 0;
380 std::string getCounterRefTmpAsString();
381 std::string getCounterAggTmpAsString();
382
383 /// Helpers to convert Clang's SourceLocation to a MLIR Location.
384 mlir::Location getLoc(clang::SourceLocation srcLoc);
385 mlir::Location getLoc(clang::SourceRange srcLoc);
386 mlir::Location getLoc(mlir::Location lhs, mlir::Location rhs);
387
388 const clang::LangOptions &getLangOpts() const { return cgm.getLangOpts(); }
389
390 /// True if an insertion point is defined. If not, this indicates that the
391 /// current code being emitted is unreachable.
392 /// FIXME(cir): we need to inspect this and perhaps use a cleaner mechanism
393 /// since we don't yet force null insertion point to designate behavior (like
394 /// LLVM's codegen does) and we probably shouldn't.
395 bool haveInsertPoint() const {
396 return builder.getInsertionBlock() != nullptr;
397 }
398
399 // Wrapper for function prototype sources. Wraps either a FunctionProtoType or
400 // an ObjCMethodDecl.
402 llvm::PointerUnion<const clang::FunctionProtoType *,
403 const clang::ObjCMethodDecl *>
405
408 };
409
411
412 /// An abstract representation of regular/ObjC call/message targets.
414 /// The function declaration of the callee.
415 [[maybe_unused]] const clang::Decl *calleeDecl;
416
417 public:
418 AbstractCallee() : calleeDecl(nullptr) {}
419 AbstractCallee(const clang::FunctionDecl *fd) : calleeDecl(fd) {}
420
421 bool hasFunctionDecl() const {
422 return llvm::isa_and_nonnull<clang::FunctionDecl>(calleeDecl);
423 }
424
425 unsigned getNumParams() const {
426 if (const auto *fd = llvm::dyn_cast<clang::FunctionDecl>(calleeDecl))
427 return fd->getNumParams();
428 return llvm::cast<clang::ObjCMethodDecl>(calleeDecl)->param_size();
429 }
430
431 const clang::ParmVarDecl *getParamDecl(unsigned I) const {
432 if (const auto *fd = llvm::dyn_cast<clang::FunctionDecl>(calleeDecl))
433 return fd->getParamDecl(I);
434 return *(llvm::cast<clang::ObjCMethodDecl>(calleeDecl)->param_begin() +
435 I);
436 }
437 };
438
439 void finishFunction(SourceLocation endLoc);
440
441 /// Determine whether the given initializer is trivial in the sense
442 /// that it requires no code to be generated.
443 bool isTrivialInitializer(const Expr *init);
444
445 /// If the specified expression does not fold to a constant, or if it does but
446 /// contains a label, return false. If it constant folds return true and set
447 /// the boolean result in Result.
448 bool constantFoldsToBool(const clang::Expr *cond, bool &resultBool,
449 bool allowLabels = false);
451 llvm::APSInt &resultInt,
452 bool allowLabels = false);
453
454 /// Return true if the statement contains a label in it. If
455 /// this statement is not executed normally, it not containing a label means
456 /// that we can just remove the code.
457 bool containsLabel(const clang::Stmt *s, bool ignoreCaseStmts = false);
458
459 class ConstantEmission {
460 // Cannot use mlir::TypedAttr directly here because of bit availability.
461 llvm::PointerIntPair<mlir::Attribute, 1, bool> valueAndIsReference;
462 ConstantEmission(mlir::TypedAttr c, bool isReference)
463 : valueAndIsReference(c, isReference) {}
464
465 public:
467 static ConstantEmission forReference(mlir::TypedAttr c) {
468 return ConstantEmission(c, true);
469 }
470 static ConstantEmission forValue(mlir::TypedAttr c) {
471 return ConstantEmission(c, false);
472 }
473
474 explicit operator bool() const {
475 return valueAndIsReference.getOpaqueValue() != nullptr;
476 }
477
478 bool isReference() const { return valueAndIsReference.getInt(); }
480 assert(isReference());
481 cgf.cgm.errorNYI(refExpr->getSourceRange(),
482 "ConstantEmission::getReferenceLValue");
483 return {};
484 }
485
486 mlir::TypedAttr getValue() const {
487 assert(!isReference());
488 return mlir::cast<mlir::TypedAttr>(valueAndIsReference.getPointer());
489 }
490 };
491
492 ConstantEmission tryEmitAsConstant(const DeclRefExpr *refExpr);
493 ConstantEmission tryEmitAsConstant(const MemberExpr *me);
494
497 /// The address of the alloca for languages with explicit address space
498 /// (e.g. OpenCL) or alloca casted to generic pointer for address space
499 /// agnostic languages (e.g. C++). Invalid if the variable was emitted
500 /// as a global constant.
502
503 /// True if the variable is of aggregate type and has a constant
504 /// initializer.
506
507 /// True if the variable is a __block variable that is captured by an
508 /// escaping block.
509 bool isEscapingByRef = false;
510
511 /// True if the variable was emitted as an offload recipe, and thus doesn't
512 /// have the same sort of alloca initialization.
513 bool emittedAsOffload = false;
514
515 mlir::Value nrvoFlag{};
516
517 struct Invalid {};
519
522
524
525 bool wasEmittedAsGlobal() const { return !addr.isValid(); }
526
528
529 /// Returns the raw, allocated address, which is not necessarily
530 /// the address of the object itself. It is casted to default
531 /// address space for address space agnostic languages.
532 Address getAllocatedAddress() const { return addr; }
533
534 // Changes the stored address for the emission. This function should only
535 // be used in extreme cases, and isn't required to model normal AST
536 // initialization/variables.
538
539 /// Returns the address of the object within this declaration.
540 /// Note that this does not chase the forwarding pointer for
541 /// __block decls.
543 if (!isEscapingByRef)
544 return addr;
545
547 return Address::invalid();
548 }
549 };
550
551 /// Perform the usual unary conversions on the specified expression and
552 /// compare the result against zero, returning an Int1Ty value.
553 mlir::Value evaluateExprAsBool(const clang::Expr *e);
554
555 cir::GlobalOp addInitializerToStaticVarDecl(const VarDecl &d,
556 cir::GlobalOp gv,
557 cir::GetGlobalOp gvAddr);
558
559 /// Enter the cleanups necessary to complete the given phase of destruction
560 /// for a destructor. The end result should call destructors on members and
561 /// base classes in reverse order of their construction.
563
564 /// Determines whether an EH cleanup is required to destroy a type
565 /// with the given destruction kind.
566 /// TODO(cir): could be shared with Clang LLVM codegen
568 switch (kind) {
570 return false;
574 return getLangOpts().Exceptions;
576 return getLangOpts().Exceptions &&
577 cgm.getCodeGenOpts().ObjCAutoRefCountExceptions;
578 }
579 llvm_unreachable("bad destruction kind");
580 }
581
585
586 /// Set the address of a local variable.
588 assert(!localDeclMap.count(vd) && "Decl already exists in LocalDeclMap!");
589 localDeclMap.insert({vd, addr});
590
591 // Add to the symbol table if not there already.
592 if (symbolTable.count(vd))
593 return;
594 symbolTable.insert(vd, addr.getPointer());
595 }
596
597 // A class to allow reverting changes to a var-decl's registration to the
598 // localDeclMap. This is used in cases where things are being inserted into
599 // the variable list but don't follow normal lookup/search rules, like in
600 // OpenACC recipe generation.
602 CIRGenFunction &cgf;
603 const VarDecl *vd;
604 bool shouldDelete = false;
605 Address oldAddr = Address::invalid();
606
607 public:
609 : cgf(cgf), vd(vd) {
610 auto mapItr = cgf.localDeclMap.find(vd);
611
612 if (mapItr != cgf.localDeclMap.end())
613 oldAddr = mapItr->second;
614 else
615 shouldDelete = true;
616 }
617
619 if (shouldDelete)
620 cgf.localDeclMap.erase(vd);
621 else
622 cgf.localDeclMap.insert_or_assign(vd, oldAddr);
623 }
624 };
625
627
630
631 static bool
633
640
643
647 const clang::CXXRecordDecl *nearestVBase,
648 clang::CharUnits offsetFromNearestVBase,
649 bool baseIsNonVirtualPrimaryBase,
650 const clang::CXXRecordDecl *vtableClass,
651 VisitedVirtualBasesSetTy &vbases, VPtrsVector &vptrs);
652 /// Return the Value of the vtable pointer member pointed to by thisAddr.
653 mlir::Value getVTablePtr(mlir::Location loc, Address thisAddr,
654 const clang::CXXRecordDecl *vtableClass);
655
656 /// Returns whether we should perform a type checked load when loading a
657 /// virtual function for virtual calls to members of RD. This is generally
658 /// true when both vcall CFI and whole-program-vtables are enabled.
660
661 /// Source location information about the default argument or member
662 /// initializer expression we're evaluating, if any.
666
667 /// A scope within which we are constructing the fields of an object which
668 /// might use a CXXDefaultInitExpr. This stashes away a 'this' value to use if
669 /// we need to evaluate the CXXDefaultInitExpr within the evaluation.
671 public:
673 : cgf(cgf), oldCXXDefaultInitExprThis(cgf.cxxDefaultInitExprThis) {
674 cgf.cxxDefaultInitExprThis = thisAddr;
675 }
677 cgf.cxxDefaultInitExprThis = oldCXXDefaultInitExprThis;
678 }
679
680 private:
681 CIRGenFunction &cgf;
682 Address oldCXXDefaultInitExprThis;
683 };
684
685 /// The scope of a CXXDefaultInitExpr. Within this scope, the value of 'this'
686 /// is overridden to be the object under construction.
688 public:
693 cgf.cxxThisValue = cgf.cxxDefaultInitExprThis.getPointer();
694 cgf.cxxThisAlignment = cgf.cxxDefaultInitExprThis.getAlignment();
695 }
697 cgf.cxxThisValue = oldCXXThisValue;
698 cgf.cxxThisAlignment = oldCXXThisAlignment;
699 }
700
701 public:
703 mlir::Value oldCXXThisValue;
706 };
707
709 LValue makeNaturalAlignAddrLValue(mlir::Value val, QualType ty);
710
711 /// Construct an address with the natural alignment of T. If a pointer to T
712 /// is expected to be signed, the pointer passed to this function must have
713 /// been signed, and the returned Address will have the pointer authentication
714 /// information needed to authenticate the signed pointer.
716 CharUnits alignment,
717 bool forPointeeType = false,
718 LValueBaseInfo *baseInfo = nullptr) {
719 if (alignment.isZero())
720 alignment = cgm.getNaturalTypeAlignment(t, baseInfo);
721 return Address(ptr, convertTypeForMem(t), alignment);
722 }
723
725 Address value, const CXXRecordDecl *derived,
726 llvm::iterator_range<CastExpr::path_const_iterator> path,
727 bool nullCheckValue, SourceLocation loc);
728
729 /// Return the VTT parameter that should be passed to a base
730 /// constructor/destructor with virtual bases.
731 /// FIXME: VTTs are Itanium ABI-specific, so the definition should move
732 /// to ItaniumCXXABI.cpp together with all the references to VTT.
733 mlir::Value getVTTParameter(GlobalDecl gd, bool forVirtualBase,
734 bool delegating);
735
738 return makeAddrLValue(addr, ty, LValueBaseInfo(source));
739 }
740
742 return LValue::makeAddr(addr, ty, baseInfo);
743 }
744
745 void initializeVTablePointers(mlir::Location loc,
746 const clang::CXXRecordDecl *rd);
747 void initializeVTablePointer(mlir::Location loc, const VPtr &vptr);
748
750
751 /// Return the address of a local variable.
753 auto it = localDeclMap.find(vd);
754 assert(it != localDeclMap.end() &&
755 "Invalid argument to getAddrOfLocalVar(), no decl!");
756 return it->second;
757 }
758
760 mlir::Type fieldType, unsigned index);
761
762 /// Given an opaque value expression, return its LValue mapping if it exists,
763 /// otherwise create one.
765
766 /// Given an opaque value expression, return its RValue mapping if it exists,
767 /// otherwise create one.
769
770 /// Load the value for 'this'. This function is only valid while generating
771 /// code for an C++ member function.
772 /// FIXME(cir): this should return a mlir::Value!
773 mlir::Value loadCXXThis() {
774 assert(cxxThisValue && "no 'this' value for this function");
775 return cxxThisValue;
776 }
778
779 /// Load the VTT parameter to base constructors/destructors have virtual
780 /// bases. FIXME: Every place that calls LoadCXXVTT is something that needs to
781 /// be abstracted properly.
782 mlir::Value loadCXXVTT() {
783 assert(cxxStructorImplicitParamValue && "no VTT value for this function");
785 }
786
787 /// Convert the given pointer to a complete class to the given direct base.
789 Address value,
790 const CXXRecordDecl *derived,
791 const CXXRecordDecl *base,
792 bool baseIsVirtual);
793
794 /// Determine whether a return value slot may overlap some other object.
796 // FIXME: Assuming no overlap here breaks guaranteed copy elision for base
797 // class subobjects. These cases may need to be revisited depending on the
798 // resolution of the relevant core issue.
800 }
801
802 /// Determine whether a base class initialization may overlap some other
803 /// object.
805 const CXXRecordDecl *baseRD,
806 bool isVirtual);
807
808 /// Get an appropriate 'undef' rvalue for the given type.
809 /// TODO: What's the equivalent for MLIR? Currently we're only using this for
810 /// void types so it just returns RValue::get(nullptr) but it'll need
811 /// addressed later.
813
814 cir::FuncOp generateCode(clang::GlobalDecl gd, cir::FuncOp fn,
815 cir::FuncType funcType);
816
818 FunctionArgList &args);
819
820 /// Emit code for the start of a function.
821 /// \param loc The location to be associated with the function.
822 /// \param startLoc The location of the function body.
824 cir::FuncOp fn, cir::FuncType funcType,
826 clang::SourceLocation startLoc);
827
828 /// The cleanup depth enclosing all the cleanups associated with the
829 /// parameters.
831
832 /// Takes the old cleanup stack size and emits the cleanup blocks
833 /// that have been added.
834 void popCleanupBlocks(EHScopeStack::stable_iterator oldCleanupStackDepth);
835 void popCleanupBlock();
836
837 /// Push a cleanup to be run at the end of the current full-expression. Safe
838 /// against the possibility that we're currently inside a
839 /// conditionally-evaluated expression.
840 template <class T, class... As>
841 void pushFullExprCleanup(CleanupKind kind, As... a) {
842 // If we're not in a conditional branch, or if none of the
843 // arguments requires saving, then use the unconditional cleanup.
845 return ehStack.pushCleanup<T>(kind, a...);
846
847 cgm.errorNYI("pushFullExprCleanup in conditional branch");
848 }
849
850 /// Enters a new scope for capturing cleanups, all of which
851 /// will be executed once the scope is exited.
852 class RunCleanupsScope {
853 EHScopeStack::stable_iterator cleanupStackDepth, oldCleanupStackDepth;
854
855 protected:
857
858 private:
859 RunCleanupsScope(const RunCleanupsScope &) = delete;
860 void operator=(const RunCleanupsScope &) = delete;
861
862 protected:
864
865 public:
866 /// Enter a new cleanup scope.
869 cleanupStackDepth = cgf.ehStack.stable_begin();
870 oldCleanupStackDepth = cgf.currentCleanupStackDepth;
871 cgf.currentCleanupStackDepth = cleanupStackDepth;
872 }
873
874 /// Exit this cleanup scope, emitting any accumulated cleanups.
879
880 /// Force the emission of cleanups now, instead of waiting
881 /// until this object is destroyed.
883 assert(performCleanup && "Already forced cleanup");
884 {
885 mlir::OpBuilder::InsertionGuard guard(cgf.getBuilder());
886 cgf.popCleanupBlocks(cleanupStackDepth);
887 performCleanup = false;
888 cgf.currentCleanupStackDepth = oldCleanupStackDepth;
889 }
890 }
891 };
892
893 // Cleanup stack depth of the RunCleanupsScope that was pushed most recently.
895
896public:
897 /// Represents a scope, including function bodies, compound statements, and
898 /// the substatements of if/while/do/for/switch/try statements. This class
899 /// handles any automatic cleanup, along with the return value.
900 struct LexicalScope : public RunCleanupsScope {
901 private:
902 // Block containing cleanup code for things initialized in this
903 // lexical context (scope).
904 mlir::Block *cleanupBlock = nullptr;
905
906 // Points to the scope entry block. This is useful, for instance, for
907 // helping to insert allocas before finalizing any recursive CodeGen from
908 // switches.
909 mlir::Block *entryBlock;
910
911 LexicalScope *parentScope = nullptr;
912
913 // Only Regular is used at the moment. Support for other kinds will be
914 // added as the relevant statements/expressions are upstreamed.
915 enum Kind {
916 Regular, // cir.if, cir.scope, if_regions
917 Ternary, // cir.ternary
918 Switch, // cir.switch
919 Try, // cir.try
920 GlobalInit // cir.global initialization code
921 };
922 Kind scopeKind = Kind::Regular;
923
924 // The scope return value.
925 mlir::Value retVal = nullptr;
926
927 mlir::Location beginLoc;
928 mlir::Location endLoc;
929
930 public:
931 unsigned depth = 0;
932
933 LexicalScope(CIRGenFunction &cgf, mlir::Location loc, mlir::Block *eb)
934 : RunCleanupsScope(cgf), entryBlock(eb), parentScope(cgf.curLexScope),
935 beginLoc(loc), endLoc(loc) {
936
937 assert(entryBlock && "LexicalScope requires an entry block");
938 cgf.curLexScope = this;
939 if (parentScope)
940 ++depth;
941
942 if (const auto fusedLoc = mlir::dyn_cast<mlir::FusedLoc>(loc)) {
943 assert(fusedLoc.getLocations().size() == 2 && "too many locations");
944 beginLoc = fusedLoc.getLocations()[0];
945 endLoc = fusedLoc.getLocations()[1];
946 }
947 }
948
949 void setRetVal(mlir::Value v) { retVal = v; }
950
951 void cleanup();
952 void restore() { cgf.curLexScope = parentScope; }
953
959
960 // ---
961 // Kind
962 // ---
963 bool isGlobalInit() { return scopeKind == Kind::GlobalInit; }
964 bool isRegular() { return scopeKind == Kind::Regular; }
965 bool isSwitch() { return scopeKind == Kind::Switch; }
966 bool isTernary() { return scopeKind == Kind::Ternary; }
967 bool isTry() { return scopeKind == Kind::Try; }
968
969 void setAsGlobalInit() { scopeKind = Kind::GlobalInit; }
970 void setAsSwitch() { scopeKind = Kind::Switch; }
971 void setAsTernary() { scopeKind = Kind::Ternary; }
972
973 // Lazy create cleanup block or return what's available.
974 mlir::Block *getOrCreateCleanupBlock(mlir::OpBuilder &builder) {
975 if (cleanupBlock)
976 return cleanupBlock;
977 cleanupBlock = createCleanupBlock(builder);
978 return cleanupBlock;
979 }
980
981 mlir::Block *getCleanupBlock(mlir::OpBuilder &builder) {
982 return cleanupBlock;
983 }
984
985 mlir::Block *createCleanupBlock(mlir::OpBuilder &builder) {
986 // Create the cleanup block but dont hook it up around just yet.
987 mlir::OpBuilder::InsertionGuard guard(builder);
988 mlir::Region *r = builder.getBlock() ? builder.getBlock()->getParent()
989 : &cgf.curFn->getRegion(0);
990 cleanupBlock = builder.createBlock(r);
991 return cleanupBlock;
992 }
993
994 // ---
995 // Return handling.
996 // ---
997
998 private:
999 // `returnBlock`, `returnLoc`, and all the functions that deal with them
1000 // will change and become more complicated when `switch` statements are
1001 // upstreamed. `case` statements within the `switch` are in the same scope
1002 // but have their own regions. Therefore the LexicalScope will need to
1003 // keep track of multiple return blocks.
1004 mlir::Block *returnBlock = nullptr;
1005 std::optional<mlir::Location> returnLoc;
1006
1007 // See the comment on `getOrCreateRetBlock`.
1008 mlir::Block *createRetBlock(CIRGenFunction &cgf, mlir::Location loc) {
1009 assert(returnBlock == nullptr && "only one return block per scope");
1010 // Create the cleanup block but don't hook it up just yet.
1011 mlir::OpBuilder::InsertionGuard guard(cgf.builder);
1012 returnBlock =
1013 cgf.builder.createBlock(cgf.builder.getBlock()->getParent());
1014 updateRetLoc(returnBlock, loc);
1015 return returnBlock;
1016 }
1017
1018 cir::ReturnOp emitReturn(mlir::Location loc);
1019 void emitImplicitReturn();
1020
1021 public:
1022 mlir::Block *getRetBlock() { return returnBlock; }
1023 mlir::Location getRetLoc(mlir::Block *b) { return *returnLoc; }
1024 void updateRetLoc(mlir::Block *b, mlir::Location loc) { returnLoc = loc; }
1025
1026 // Create the return block for this scope, or return the existing one.
1027 // This get-or-create logic is necessary to handle multiple return
1028 // statements within the same scope, which can happen if some of them are
1029 // dead code or if there is a `goto` into the middle of the scope.
1030 mlir::Block *getOrCreateRetBlock(CIRGenFunction &cgf, mlir::Location loc) {
1031 if (returnBlock == nullptr) {
1032 returnBlock = createRetBlock(cgf, loc);
1033 return returnBlock;
1034 }
1035 updateRetLoc(returnBlock, loc);
1036 return returnBlock;
1037 }
1038
1039 mlir::Block *getEntryBlock() { return entryBlock; }
1040 };
1041
1043
1044 typedef void Destroyer(CIRGenFunction &cgf, Address addr, QualType ty);
1045
1047
1048 void pushDestroy(CleanupKind kind, Address addr, QualType type,
1049 Destroyer *destroyer);
1050
1052
1053 /// ----------------------
1054 /// CIR emit functions
1055 /// ----------------------
1056public:
1057 mlir::Value emitAlignmentAssumption(mlir::Value ptrValue, QualType ty,
1058 SourceLocation loc,
1059 SourceLocation assumptionLoc,
1060 int64_t alignment,
1061 mlir::Value offsetValue = nullptr);
1062
1063 mlir::Value emitAlignmentAssumption(mlir::Value ptrValue, const Expr *expr,
1064 SourceLocation assumptionLoc,
1065 int64_t alignment,
1066 mlir::Value offsetValue = nullptr);
1067
1068private:
1069 void emitAndUpdateRetAlloca(clang::QualType type, mlir::Location loc,
1070 clang::CharUnits alignment);
1071
1072 CIRGenCallee emitDirectCallee(const GlobalDecl &gd);
1073
1074public:
1076 llvm::StringRef fieldName,
1077 unsigned fieldIndex);
1078
1079 mlir::Value emitAlloca(llvm::StringRef name, mlir::Type ty,
1080 mlir::Location loc, clang::CharUnits alignment,
1081 bool insertIntoFnEntryBlock,
1082 mlir::Value arraySize = nullptr);
1083 mlir::Value emitAlloca(llvm::StringRef name, mlir::Type ty,
1084 mlir::Location loc, clang::CharUnits alignment,
1085 mlir::OpBuilder::InsertPoint ip,
1086 mlir::Value arraySize = nullptr);
1087
1088 void emitAggregateStore(mlir::Value value, Address dest);
1089
1090 void emitAggExpr(const clang::Expr *e, AggValueSlot slot);
1091
1093
1094 /// Emit an aggregate copy.
1095 ///
1096 /// \param isVolatile \c true iff either the source or the destination is
1097 /// volatile.
1098 /// \param MayOverlap Whether the tail padding of the destination might be
1099 /// occupied by some other object. More efficient code can often be
1100 /// generated if not.
1101 void emitAggregateCopy(LValue dest, LValue src, QualType eltTy,
1102 AggValueSlot::Overlap_t mayOverlap);
1103
1104 /// Emit code to compute the specified expression which can have any type. The
1105 /// result is returned as an RValue struct. If this is an aggregate
1106 /// expression, the aggloc/agglocvolatile arguments indicate where the result
1107 /// should be returned.
1110
1111 /// Emits the code necessary to evaluate an arbitrary expression into the
1112 /// given memory location.
1113 void emitAnyExprToMem(const Expr *e, Address location, Qualifiers quals,
1114 bool isInitializer);
1115
1116 /// Similarly to emitAnyExpr(), however, the result will always be accessible
1117 /// even if no aggregate location is provided.
1119
1120 void emitAnyExprToExn(const Expr *e, Address addr);
1121
1122 void emitArrayDestroy(mlir::Value begin, mlir::Value numElements,
1123 QualType elementType, CharUnits elementAlign,
1124 Destroyer *destroyer);
1125
1126 mlir::Value emitArrayLength(const clang::ArrayType *arrayType,
1127 QualType &baseType, Address &addr);
1129
1131 LValueBaseInfo *baseInfo = nullptr);
1132
1133 mlir::LogicalResult emitAsmStmt(const clang::AsmStmt &s);
1134
1136 void emitAtomicInit(Expr *init, LValue dest);
1137
1139 mlir::OpBuilder::InsertPoint ip = {});
1140
1141 /// Emit code and set up symbol table for a variable declaration with auto,
1142 /// register, or no storage class specifier. These turn into simple stack
1143 /// objects, globals depending on target.
1144 void emitAutoVarDecl(const clang::VarDecl &d);
1145
1146 void emitAutoVarCleanups(const AutoVarEmission &emission);
1147 /// Emit the initializer for an allocated variable. If this call is not
1148 /// associated with the call to emitAutoVarAlloca (as the address of the
1149 /// emission is not directly an alloca), the allocatedSeparately parameter can
1150 /// be used to suppress the assertions. However, this should only be used in
1151 /// extreme cases, as it doesn't properly reflect the language/AST.
1152 void emitAutoVarInit(const AutoVarEmission &emission);
1153 void emitAutoVarTypeCleanup(const AutoVarEmission &emission,
1155
1156 void maybeEmitDeferredVarDeclInit(const VarDecl *vd);
1157
1158 void emitBaseInitializer(mlir::Location loc, const CXXRecordDecl *classDecl,
1159 CXXCtorInitializer *baseInit);
1160
1162
1163 mlir::LogicalResult emitBreakStmt(const clang::BreakStmt &s);
1164
1165 RValue emitBuiltinExpr(const clang::GlobalDecl &gd, unsigned builtinID,
1167
1168 RValue emitCall(const CIRGenFunctionInfo &funcInfo,
1170 const CallArgList &args, cir::CIRCallOpInterface *callOp,
1171 mlir::Location loc);
1174 const CallArgList &args,
1175 cir::CIRCallOpInterface *callOrTryCall = nullptr) {
1176 assert(currSrcLoc && "source location must have been set");
1177 return emitCall(funcInfo, callee, returnValue, args, callOrTryCall,
1178 *currSrcLoc);
1179 }
1180
1181 RValue emitCall(clang::QualType calleeTy, const CIRGenCallee &callee,
1183 void emitCallArg(CallArgList &args, const clang::Expr *e,
1184 clang::QualType argType);
1185 void emitCallArgs(
1186 CallArgList &args, PrototypeWrapper prototype,
1187 llvm::iterator_range<clang::CallExpr::const_arg_iterator> argRange,
1188 AbstractCallee callee = AbstractCallee(), unsigned paramsToSkip = 0);
1193
1194 template <typename T>
1195 mlir::LogicalResult emitCaseDefaultCascade(const T *stmt, mlir::Type condType,
1196 mlir::ArrayAttr value,
1197 cir::CaseOpKind kind,
1198 bool buildingTopLevelCase);
1199
1200 mlir::LogicalResult emitCaseStmt(const clang::CaseStmt &s,
1201 mlir::Type condType,
1202 bool buildingTopLevelCase);
1203
1204 LValue emitCastLValue(const CastExpr *e);
1205
1206 /// Emits an argument for a call to a `__builtin_assume`. If the builtin
1207 /// sanitizer is enabled, a runtime check is also emitted.
1208 mlir::Value emitCheckedArgForAssume(const Expr *e);
1209
1210 /// Emit a conversion from the specified complex type to the specified
1211 /// destination type, where the destination type is an LLVM scalar type.
1212 mlir::Value emitComplexToScalarConversion(mlir::Value src, QualType srcTy,
1213 QualType dstTy, SourceLocation loc);
1214
1217
1219
1220 mlir::LogicalResult emitCoroutineBody(const CoroutineBodyStmt &s);
1221 cir::CallOp emitCoroEndBuiltinCall(mlir::Location loc, mlir::Value nullPtr);
1222 cir::CallOp emitCoroIDBuiltinCall(mlir::Location loc, mlir::Value nullPtr);
1223
1224 void emitDestroy(Address addr, QualType type, Destroyer *destroyer);
1225
1227
1228 mlir::LogicalResult emitContinueStmt(const clang::ContinueStmt &s);
1229
1231 AggValueSlot dest);
1232
1235 Address arrayBegin, const CXXConstructExpr *e,
1236 bool newPointerIsChecked,
1237 bool zeroInitialize = false);
1239 mlir::Value numElements, Address arrayBase,
1240 const CXXConstructExpr *e,
1241 bool newPointerIsChecked,
1242 bool zeroInitialize);
1244 clang::CXXCtorType type, bool forVirtualBase,
1245 bool delegating, AggValueSlot thisAVS,
1246 const clang::CXXConstructExpr *e);
1247
1249 clang::CXXCtorType type, bool forVirtualBase,
1250 bool delegating, Address thisAddr,
1252
1253 void emitCXXDeleteExpr(const CXXDeleteExpr *e);
1254
1256 bool forVirtualBase, bool delegating,
1257 Address thisAddr, QualType thisTy);
1258
1260 mlir::Value thisVal, QualType thisTy,
1261 mlir::Value implicitParam,
1262 QualType implicitParamTy, const CallExpr *e);
1263
1264 mlir::LogicalResult emitCXXForRangeStmt(const CXXForRangeStmt &s,
1266
1269
1271 const clang::CXXMethodDecl *md, const CIRGenCallee &callee,
1272 ReturnValueSlot returnValue, mlir::Value thisPtr,
1273 mlir::Value implicitParam, clang::QualType implicitParamTy,
1274 const clang::CallExpr *ce, CallArgList *rtlArgs);
1275
1277 const clang::CallExpr *ce, const clang::CXXMethodDecl *md,
1278 ReturnValueSlot returnValue, bool hasQualifier,
1279 clang::NestedNameSpecifier qualifier, bool isArrow,
1280 const clang::Expr *base);
1281
1282 mlir::Value emitCXXNewExpr(const CXXNewExpr *e);
1283
1284 void emitNewArrayInitializer(const CXXNewExpr *E, QualType ElementType,
1285 mlir::Type ElementTy, Address BeginPtr,
1286 mlir::Value NumElements,
1287 mlir::Value AllocSizeWithoutCookie);
1288
1290 const CXXMethodDecl *md,
1292
1294
1295 void emitCXXTemporary(const CXXTemporary *temporary, QualType tempType,
1296 Address ptr);
1297
1298 void emitCXXThrowExpr(const CXXThrowExpr *e);
1299
1300 mlir::LogicalResult emitCXXTryStmt(const clang::CXXTryStmt &s);
1301
1303 clang::CXXCtorType ctorType, FunctionArgList &args);
1304
1305 // It's important not to confuse this and emitDelegateCXXConstructorCall.
1306 // Delegating constructors are the C++11 feature. The constructor delegate
1307 // optimization is used to reduce duplication in the base and complete
1308 // constructors where they are substantially the same.
1310 const FunctionArgList &args);
1311
1312 void emitDeleteCall(const FunctionDecl *deleteFD, mlir::Value ptr,
1313 QualType deleteTy);
1314
1315 mlir::LogicalResult emitDoStmt(const clang::DoStmt &s);
1316
1317 mlir::Value emitDynamicCast(Address thisAddr, const CXXDynamicCastExpr *dce);
1318
1319 /// Emit an expression as an initializer for an object (variable, field, etc.)
1320 /// at the given location. The expression is not necessarily the normal
1321 /// initializer for the object, and the address is not necessarily
1322 /// its normal location.
1323 ///
1324 /// \param init the initializing expression
1325 /// \param d the object to act as if we're initializing
1326 /// \param lvalue the lvalue to initialize
1327 /// \param capturedByInit true if \p d is a __block variable whose address is
1328 /// potentially changed by the initializer
1329 void emitExprAsInit(const clang::Expr *init, const clang::ValueDecl *d,
1330 LValue lvalue, bool capturedByInit = false);
1331
1332 mlir::LogicalResult emitFunctionBody(const clang::Stmt *body);
1333
1334 mlir::LogicalResult emitGotoStmt(const clang::GotoStmt &s);
1335
1337
1339 clang::Expr *init);
1340
1342
1343 mlir::Value emitPromotedComplexExpr(const Expr *e, QualType promotionType);
1344
1345 mlir::Value emitPromotedScalarExpr(const Expr *e, QualType promotionType);
1346
1347 mlir::Value emitPromotedValue(mlir::Value result, QualType promotionType);
1348
1349 void emitReturnOfRValue(mlir::Location loc, RValue rv, QualType ty);
1350
1351 /// Emit the computation of the specified expression of scalar type.
1352 mlir::Value emitScalarExpr(const clang::Expr *e);
1353
1354 mlir::Value emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv,
1355 cir::UnaryOpKind kind, bool isPre);
1356
1357 /// Build a debug stoppoint if we are emitting debug info.
1358 void emitStopPoint(const Stmt *s);
1359
1360 // Build CIR for a statement. useCurrentScope should be true if no
1361 // new scopes need be created when finding a compound statement.
1362 mlir::LogicalResult emitStmt(const clang::Stmt *s, bool useCurrentScope,
1363 llvm::ArrayRef<const Attr *> attrs = {});
1364
1365 mlir::LogicalResult emitSimpleStmt(const clang::Stmt *s,
1366 bool useCurrentScope);
1367
1368 mlir::LogicalResult emitForStmt(const clang::ForStmt &s);
1369
1370 void emitForwardingCallToLambda(const CXXMethodDecl *lambdaCallOperator,
1371 CallArgList &callArgs);
1372
1373 /// Emit the computation of the specified expression of complex type,
1374 /// returning the result.
1375 mlir::Value emitComplexExpr(const Expr *e);
1376
1377 void emitComplexExprIntoLValue(const Expr *e, LValue dest, bool isInit);
1378
1379 mlir::Value emitComplexPrePostIncDec(const UnaryOperator *e, LValue lv,
1380 cir::UnaryOpKind op, bool isPre);
1381
1385 mlir::Value &result);
1386
1387 mlir::LogicalResult
1388 emitCompoundStmt(const clang::CompoundStmt &s, Address *lastValue = nullptr,
1390
1391 mlir::LogicalResult
1393 Address *lastValue = nullptr,
1395
1396 void emitDecl(const clang::Decl &d, bool evaluateConditionDecl = false);
1397 mlir::LogicalResult emitDeclStmt(const clang::DeclStmt &s);
1399
1400 mlir::LogicalResult emitDefaultStmt(const clang::DefaultStmt &s,
1401 mlir::Type condType,
1402 bool buildingTopLevelCase);
1403
1405 clang::CXXCtorType ctorType,
1406 const FunctionArgList &args,
1408
1409 /// We are performing a delegate call; that is, the current function is
1410 /// delegating to another one. Produce a r-value suitable for passing the
1411 /// given parameter.
1412 void emitDelegateCallArg(CallArgList &args, const clang::VarDecl *param,
1414
1415 /// Emit an `if` on a boolean condition to the specified blocks.
1416 /// FIXME: Based on the condition, this might try to simplify the codegen of
1417 /// the conditional based on the branch.
1418 /// In the future, we may apply code generation simplifications here,
1419 /// similar to those used in classic LLVM codegen
1420 /// See `EmitBranchOnBoolExpr` for inspiration.
1421 mlir::LogicalResult emitIfOnBoolExpr(const clang::Expr *cond,
1422 const clang::Stmt *thenS,
1423 const clang::Stmt *elseS);
1424 cir::IfOp emitIfOnBoolExpr(const clang::Expr *cond,
1425 BuilderCallbackRef thenBuilder,
1426 mlir::Location thenLoc,
1427 BuilderCallbackRef elseBuilder,
1428 std::optional<mlir::Location> elseLoc = {});
1429
1430 mlir::Value emitOpOnBoolExpr(mlir::Location loc, const clang::Expr *cond);
1431
1432 mlir::LogicalResult emitLabel(const clang::LabelDecl &d);
1433 mlir::LogicalResult emitLabelStmt(const clang::LabelStmt &s);
1434
1437
1438 mlir::LogicalResult emitIfStmt(const clang::IfStmt &s);
1439
1440 /// Emit code to compute the specified expression,
1441 /// ignoring the result.
1442 void emitIgnoredExpr(const clang::Expr *e);
1443
1444 RValue emitLoadOfBitfieldLValue(LValue lv, SourceLocation loc);
1445
1446 /// Load a complex number from the specified l-value.
1447 mlir::Value emitLoadOfComplex(LValue src, SourceLocation loc);
1448
1449 /// Given an expression that represents a value lvalue, this method emits
1450 /// the address of the lvalue, then loads the result as an rvalue,
1451 /// returning the rvalue.
1452 RValue emitLoadOfLValue(LValue lv, SourceLocation loc);
1453
1454 Address emitLoadOfReference(LValue refLVal, mlir::Location loc,
1455 LValueBaseInfo *pointeeBaseInfo);
1456 LValue emitLoadOfReferenceLValue(Address refAddr, mlir::Location loc,
1457 QualType refTy, AlignmentSource source);
1458
1459 /// EmitLoadOfScalar - Load a scalar value from an address, taking
1460 /// care to appropriately convert from the memory representation to
1461 /// the LLVM value representation. The l-value must be a simple
1462 /// l-value.
1463 mlir::Value emitLoadOfScalar(LValue lvalue, SourceLocation loc);
1464 mlir::Value emitLoadOfScalar(Address addr, bool isVolatile, QualType ty,
1465 SourceLocation loc, LValueBaseInfo baseInfo);
1466
1467 /// Emit code to compute a designator that specifies the location
1468 /// of the expression.
1469 /// FIXME: document this function better.
1470 LValue emitLValue(const clang::Expr *e);
1471 LValue emitLValueForBitField(LValue base, const FieldDecl *field);
1472 LValue emitLValueForField(LValue base, const clang::FieldDecl *field);
1473
1474 LValue emitLValueForLambdaField(const FieldDecl *field);
1475 LValue emitLValueForLambdaField(const FieldDecl *field,
1476 mlir::Value thisValue);
1477
1478 /// Like emitLValueForField, excpet that if the Field is a reference, this
1479 /// will return the address of the reference and not the address of the value
1480 /// stored in the reference.
1481 LValue emitLValueForFieldInitialization(LValue base,
1482 const clang::FieldDecl *field,
1483 llvm::StringRef fieldName);
1484
1486
1487 LValue emitMemberExpr(const MemberExpr *e);
1488
1489 /// Given an expression with a pointer type, emit the value and compute our
1490 /// best estimate of the alignment of the pointee.
1491 ///
1492 /// One reasonable way to use this information is when there's a language
1493 /// guarantee that the pointer must be aligned to some stricter value, and
1494 /// we're simply trying to ensure that sufficiently obvious uses of under-
1495 /// aligned objects don't get miscompiled; for example, a placement new
1496 /// into the address of a local variable. In such a case, it's quite
1497 /// reasonable to just ignore the returned alignment when it isn't from an
1498 /// explicit source.
1500 LValueBaseInfo *baseInfo = nullptr);
1501
1502 /// Emits a reference binding to the passed in expression.
1503 RValue emitReferenceBindingToExpr(const Expr *e);
1504
1505 mlir::LogicalResult emitReturnStmt(const clang::ReturnStmt &s);
1506
1507 RValue emitRotate(const CallExpr *e, bool isRotateLeft);
1508
1509 mlir::Value emitScalarConstant(const ConstantEmission &constant, Expr *e);
1510
1511 /// Emit a conversion from the specified type to the specified destination
1512 /// type, both of which are CIR scalar types.
1513 mlir::Value emitScalarConversion(mlir::Value src, clang::QualType srcType,
1514 clang::QualType dstType,
1516
1517 void emitScalarInit(const clang::Expr *init, mlir::Location loc,
1518 LValue lvalue, bool capturedByInit = false);
1519
1520 void emitStaticVarDecl(const VarDecl &d, cir::GlobalLinkageKind linkage);
1521
1522 void emitStoreOfComplex(mlir::Location loc, mlir::Value v, LValue dest,
1523 bool isInit);
1524
1525 void emitStoreOfScalar(mlir::Value value, Address addr, bool isVolatile,
1526 clang::QualType ty, bool isInit = false,
1527 bool isNontemporal = false);
1528 void emitStoreOfScalar(mlir::Value value, LValue lvalue, bool isInit);
1529
1530 /// Store the specified rvalue into the specified
1531 /// lvalue, where both are guaranteed to the have the same type, and that type
1532 /// is 'Ty'.
1533 void emitStoreThroughLValue(RValue src, LValue dst, bool isInit = false);
1534
1535 mlir::Value emitStoreThroughBitfieldLValue(RValue src, LValue dstresult);
1536
1537 LValue emitStringLiteralLValue(const StringLiteral *e,
1538 llvm::StringRef name = ".str");
1539
1540 mlir::LogicalResult emitSwitchBody(const clang::Stmt *s);
1541 mlir::LogicalResult emitSwitchCase(const clang::SwitchCase &s,
1542 bool buildingTopLevelCase);
1543 mlir::LogicalResult emitSwitchStmt(const clang::SwitchStmt &s);
1544
1545 /// Given a value and its clang type, returns the value casted to its memory
1546 /// representation.
1547 /// Note: CIR defers most of the special casting to the final lowering passes
1548 /// to conserve the high level information.
1549 mlir::Value emitToMemory(mlir::Value value, clang::QualType ty);
1550
1551 /// Emit a trap instruction, which is used to abort the program in an abnormal
1552 /// way, usually for debugging purposes.
1553 /// \p createNewBlock indicates whether to create a new block for the IR
1554 /// builder. Since the `cir.trap` operation is a terminator, operations that
1555 /// follow a trap cannot be emitted after `cir.trap` in the same block. To
1556 /// ensure these operations get emitted successfully, you need to create a new
1557 /// dummy block and set the insertion point there before continuing from the
1558 /// trap operation.
1559 void emitTrap(mlir::Location loc, bool createNewBlock);
1560
1561 LValue emitUnaryOpLValue(const clang::UnaryOperator *e);
1562
1563 mlir::Value emitUnPromotedValue(mlir::Value result, QualType unPromotionType);
1564
1565 /// Emit a reached-unreachable diagnostic if \p loc is valid and runtime
1566 /// checking is enabled. Otherwise, just emit an unreachable instruction.
1567 /// \p createNewBlock indicates whether to create a new block for the IR
1568 /// builder. Since the `cir.unreachable` operation is a terminator, operations
1569 /// that follow an unreachable point cannot be emitted after `cir.unreachable`
1570 /// in the same block. To ensure these operations get emitted successfully,
1571 /// you need to create a dummy block and set the insertion point there before
1572 /// continuing from the unreachable point.
1573 void emitUnreachable(clang::SourceLocation loc, bool createNewBlock);
1574
1575 /// This method handles emission of any variable declaration
1576 /// inside a function, including static vars etc.
1577 void emitVarDecl(const clang::VarDecl &d);
1578
1580
1581 mlir::LogicalResult emitWhileStmt(const clang::WhileStmt &s);
1582
1583 /// Given an assignment `*lhs = rhs`, emit a test that checks if \p rhs is
1584 /// nonnull, if 1\p LHS is marked _Nonnull.
1585 void emitNullabilityCheck(LValue lhs, mlir::Value rhs,
1587
1588 /// An object to manage conditionally-evaluated expressions.
1590 CIRGenFunction &cgf;
1591 mlir::OpBuilder::InsertPoint insertPt;
1592
1593 public:
1595 : cgf(cgf), insertPt(cgf.builder.saveInsertionPoint()) {}
1596 ConditionalEvaluation(CIRGenFunction &cgf, mlir::OpBuilder::InsertPoint ip)
1597 : cgf(cgf), insertPt(ip) {}
1598
1600 assert(cgf.outermostConditional != this);
1601 if (!cgf.outermostConditional)
1602 cgf.outermostConditional = this;
1603 }
1604
1606 assert(cgf.outermostConditional != nullptr);
1607 if (cgf.outermostConditional == this)
1608 cgf.outermostConditional = nullptr;
1609 }
1610
1611 /// Returns the insertion point which will be executed prior to each
1612 /// evaluation of the conditional code. In LLVM OG, this method
1613 /// is called getStartingBlock.
1614 mlir::OpBuilder::InsertPoint getInsertPoint() const { return insertPt; }
1615 };
1616
1618 std::optional<LValue> lhs{}, rhs{};
1619 mlir::Value result{};
1620 };
1621
1622 // Return true if we're currently emitting one branch or the other of a
1623 // conditional expression.
1624 bool isInConditionalBranch() const { return outermostConditional != nullptr; }
1625
1626 void setBeforeOutermostConditional(mlir::Value value, Address addr) {
1627 assert(isInConditionalBranch());
1628 {
1629 mlir::OpBuilder::InsertionGuard guard(builder);
1630 builder.restoreInsertionPoint(outermostConditional->getInsertPoint());
1631 builder.createStore(
1632 value.getLoc(), value, addr, /*isVolatile=*/false,
1633 mlir::IntegerAttr::get(
1634 mlir::IntegerType::get(value.getContext(), 64),
1635 (uint64_t)addr.getAlignment().getAsAlign().value()));
1636 }
1637 }
1638
1639 // Points to the outermost active conditional control. This is used so that
1640 // we know if a temporary should be destroyed conditionally.
1642
1643 /// An RAII object to record that we're evaluating a statement
1644 /// expression.
1646 CIRGenFunction &cgf;
1647
1648 /// We have to save the outermost conditional: cleanups in a
1649 /// statement expression aren't conditional just because the
1650 /// StmtExpr is.
1651 ConditionalEvaluation *savedOutermostConditional;
1652
1653 public:
1655 : cgf(cgf), savedOutermostConditional(cgf.outermostConditional) {
1656 cgf.outermostConditional = nullptr;
1657 }
1658
1660 cgf.outermostConditional = savedOutermostConditional;
1661 }
1662 };
1663
1664 template <typename FuncTy>
1666 const FuncTy &branchGenFunc);
1667
1668 mlir::Value emitTernaryOnBoolExpr(const clang::Expr *cond, mlir::Location loc,
1669 const clang::Stmt *thenS,
1670 const clang::Stmt *elseS);
1671
1672 /// Build a "reference" to a va_list; this is either the address or the value
1673 /// of the expression, depending on how va_list is defined.
1674 Address emitVAListRef(const Expr *e);
1675
1676 /// Emits the start of a CIR variable-argument operation (`cir.va_start`)
1677 ///
1678 /// \param vaList A reference to the \c va_list as emitted by either
1679 /// \c emitVAListRef or \c emitMSVAListRef.
1680 ///
1681 /// \param count The number of arguments in \c vaList
1682 void emitVAStart(mlir::Value vaList, mlir::Value count);
1683
1684 /// Emits the end of a CIR variable-argument operation (`cir.va_start`)
1685 ///
1686 /// \param vaList A reference to the \c va_list as emitted by either
1687 /// \c emitVAListRef or \c emitMSVAListRef.
1688 void emitVAEnd(mlir::Value vaList);
1689
1690 /// Generate code to get an argument from the passed in pointer
1691 /// and update it accordingly.
1692 ///
1693 /// \param ve The \c VAArgExpr for which to generate code.
1694 ///
1695 /// \param vaListAddr Receives a reference to the \c va_list as emitted by
1696 /// either \c emitVAListRef or \c emitMSVAListRef.
1697 ///
1698 /// \returns SSA value with the argument.
1699 mlir::Value emitVAArg(VAArgExpr *ve);
1700
1701 /// ----------------------
1702 /// CIR build helpers
1703 /// -----------------
1704public:
1705 cir::AllocaOp createTempAlloca(mlir::Type ty, mlir::Location loc,
1706 const Twine &name = "tmp",
1707 mlir::Value arraySize = nullptr,
1708 bool insertIntoFnEntryBlock = false);
1709 cir::AllocaOp createTempAlloca(mlir::Type ty, mlir::Location loc,
1710 const Twine &name = "tmp",
1711 mlir::OpBuilder::InsertPoint ip = {},
1712 mlir::Value arraySize = nullptr);
1713 Address createTempAlloca(mlir::Type ty, CharUnits align, mlir::Location loc,
1714 const Twine &name = "tmp",
1715 mlir::Value arraySize = nullptr,
1716 Address *alloca = nullptr,
1717 mlir::OpBuilder::InsertPoint ip = {});
1718 Address createTempAllocaWithoutCast(mlir::Type ty, CharUnits align,
1719 mlir::Location loc,
1720 const Twine &name = "tmp",
1721 mlir::Value arraySize = nullptr,
1722 mlir::OpBuilder::InsertPoint ip = {});
1723
1724 /// Create a temporary memory object of the given type, with
1725 /// appropriate alignmen and cast it to the default address space. Returns
1726 /// the original alloca instruction by \p Alloca if it is not nullptr.
1727 Address createMemTemp(QualType t, mlir::Location loc,
1728 const Twine &name = "tmp", Address *alloca = nullptr,
1729 mlir::OpBuilder::InsertPoint ip = {});
1730 Address createMemTemp(QualType t, CharUnits align, mlir::Location loc,
1731 const Twine &name = "tmp", Address *alloca = nullptr,
1732 mlir::OpBuilder::InsertPoint ip = {});
1733
1734 //===--------------------------------------------------------------------===//
1735 // OpenACC Emission
1736 //===--------------------------------------------------------------------===//
1737private:
1738 template <typename Op>
1739 Op emitOpenACCOp(mlir::Location start, OpenACCDirectiveKind dirKind,
1740 SourceLocation dirLoc,
1741 llvm::ArrayRef<const OpenACCClause *> clauses);
1742 // Function to do the basic implementation of an operation with an Associated
1743 // Statement. Models AssociatedStmtConstruct.
1744 template <typename Op, typename TermOp>
1745 mlir::LogicalResult emitOpenACCOpAssociatedStmt(
1746 mlir::Location start, mlir::Location end, OpenACCDirectiveKind dirKind,
1747 SourceLocation dirLoc, llvm::ArrayRef<const OpenACCClause *> clauses,
1748 const Stmt *associatedStmt);
1749
1750 template <typename Op, typename TermOp>
1751 mlir::LogicalResult emitOpenACCOpCombinedConstruct(
1752 mlir::Location start, mlir::Location end, OpenACCDirectiveKind dirKind,
1753 SourceLocation dirLoc, llvm::ArrayRef<const OpenACCClause *> clauses,
1754 const Stmt *loopStmt);
1755
1756 template <typename Op>
1757 void emitOpenACCClauses(Op &op, OpenACCDirectiveKind dirKind,
1758 SourceLocation dirLoc,
1759 ArrayRef<const OpenACCClause *> clauses);
1760 // The second template argument doesn't need to be a template, since it should
1761 // always be an mlir::acc::LoopOp, but as this is a template anyway, we make
1762 // it a template argument as this way we can avoid including the OpenACC MLIR
1763 // headers here. We will count on linker failures/explicit instantiation to
1764 // ensure we don't mess this up, but it is only called from 1 place, and
1765 // instantiated 3x.
1766 template <typename ComputeOp, typename LoopOp>
1767 void emitOpenACCClauses(ComputeOp &op, LoopOp &loopOp,
1768 OpenACCDirectiveKind dirKind, SourceLocation dirLoc,
1769 ArrayRef<const OpenACCClause *> clauses);
1770
1771 // The OpenACC LoopOp requires that we have auto, seq, or independent on all
1772 // LoopOp operations for the 'none' device type case. This function checks if
1773 // the LoopOp has one, else it updates it to have one.
1774 void updateLoopOpParallelism(mlir::acc::LoopOp &op, bool isOrphan,
1776
1777 // The OpenACC 'cache' construct actually applies to the 'loop' if present. So
1778 // keep track of the 'loop' so that we can add the cache vars to it correctly.
1779 mlir::acc::LoopOp *activeLoopOp = nullptr;
1780
1781 struct ActiveOpenACCLoopRAII {
1782 CIRGenFunction &cgf;
1783 mlir::acc::LoopOp *oldLoopOp;
1784
1785 ActiveOpenACCLoopRAII(CIRGenFunction &cgf, mlir::acc::LoopOp *newOp)
1786 : cgf(cgf), oldLoopOp(cgf.activeLoopOp) {
1787 cgf.activeLoopOp = newOp;
1788 }
1789 ~ActiveOpenACCLoopRAII() { cgf.activeLoopOp = oldLoopOp; }
1790 };
1791
1792 // Keep track of the last place we inserted a 'recipe' so that we can insert
1793 // the next one in lexical order.
1794 mlir::OpBuilder::InsertPoint lastRecipeLocation;
1795
1796public:
1797 // Helper type used to store the list of important information for a 'data'
1798 // clause variable, or a 'cache' variable reference.
1800 mlir::Location beginLoc;
1801 mlir::Value varValue;
1802 std::string name;
1803 // The type of the original variable reference: that is, after 'bounds' have
1804 // removed pointers/array types/etc. So in the case of int arr[5], and a
1805 // private(arr[1]), 'origType' is 'int', but 'baseType' is 'int[5]'.
1809 // The list of types that we found when going through the bounds, which we
1810 // can use to properly set the alloca section.
1812 };
1813
1814 // Gets the collection of info required to lower and OpenACC clause or cache
1815 // construct variable reference.
1817 // Helper function to emit the integer expressions as required by an OpenACC
1818 // clause/construct.
1819 mlir::Value emitOpenACCIntExpr(const Expr *intExpr);
1820 // Helper function to emit an integer constant as an mlir int type, used for
1821 // constants in OpenACC constructs/clauses.
1822 mlir::Value createOpenACCConstantInt(mlir::Location loc, unsigned width,
1823 int64_t value);
1824
1825 mlir::LogicalResult
1827 mlir::LogicalResult emitOpenACCLoopConstruct(const OpenACCLoopConstruct &s);
1828 mlir::LogicalResult
1830 mlir::LogicalResult emitOpenACCDataConstruct(const OpenACCDataConstruct &s);
1831 mlir::LogicalResult
1833 mlir::LogicalResult
1835 mlir::LogicalResult
1837 mlir::LogicalResult emitOpenACCWaitConstruct(const OpenACCWaitConstruct &s);
1838 mlir::LogicalResult emitOpenACCInitConstruct(const OpenACCInitConstruct &s);
1839 mlir::LogicalResult
1841 mlir::LogicalResult emitOpenACCSetConstruct(const OpenACCSetConstruct &s);
1842 mlir::LogicalResult
1844 mlir::LogicalResult
1846 mlir::LogicalResult emitOpenACCCacheConstruct(const OpenACCCacheConstruct &s);
1847
1850
1851 /// Create a temporary memory object for the given aggregate type.
1852 AggValueSlot createAggTemp(QualType ty, mlir::Location loc,
1853 const Twine &name = "tmp",
1854 Address *alloca = nullptr) {
1856 return AggValueSlot::forAddr(
1857 createMemTemp(ty, loc, name, alloca), ty.getQualifiers(),
1860 }
1861
1862private:
1863 QualType getVarArgType(const Expr *arg);
1864};
1865
1866} // namespace clang::CIRGen
1867
1868#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:220
AbstractConditionalOperator - An abstract base class for ConditionalOperator and BinaryConditionalOpe...
Definition Expr.h:4287
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Definition Expr.h:2721
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition TypeBase.h:3722
AsmStmt is the base class for GCCAsmStmt and MSAsmStmt.
Definition Stmt.h: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:82
static Address invalid()
Definition Address.h:67
clang::CharUnits getAlignment() const
Definition Address.h:117
An aggregate value slot.
static AggValueSlot forAddr(Address addr, clang::Qualifiers quals, IsDestructed_t isDestructed, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed)
static AggValueSlot ignored()
Returns an aggregate value slot indicating that the aggregate value is being ignored.
AbstractCallee(const clang::FunctionDecl *fd)
const clang::ParmVarDecl * getParamDecl(unsigned I) const
CXXDefaultInitExprScope(CIRGenFunction &cgf, const CXXDefaultInitExpr *e)
An object to manage conditionally-evaluated expressions.
ConditionalEvaluation(CIRGenFunction &cgf, mlir::OpBuilder::InsertPoint ip)
mlir::OpBuilder::InsertPoint getInsertPoint() const
Returns the insertion point which will be executed prior to each evaluation of the conditional code.
static ConstantEmission forReference(mlir::TypedAttr c)
static ConstantEmission forValue(mlir::TypedAttr c)
LValue getReferenceLValue(CIRGenFunction &cgf, Expr *refExpr) const
DeclMapRevertingRAII(CIRGenFunction &cgf, const VarDecl *vd)
FieldConstructionScope(CIRGenFunction &cgf, Address thisAddr)
A non-RAII class containing all the information about a bound opaque value.
static OpaqueValueMappingData bind(CIRGenFunction &cgf, const OpaqueValueExpr *ov, const LValue &lv)
static OpaqueValueMappingData bind(CIRGenFunction &cgf, const OpaqueValueExpr *ov, const RValue &rv)
static OpaqueValueMappingData bind(CIRGenFunction &cgf, const OpaqueValueExpr *ov, const Expr *e)
OpaqueValueMapping(CIRGenFunction &cgf, const OpaqueValueExpr *opaqueValue, RValue rvalue)
OpaqueValueMapping(CIRGenFunction &cgf, const OpaqueValueExpr *opaqueValue, LValue lvalue)
OpaqueValueMapping(CIRGenFunction &cgf, const AbstractConditionalOperator *op)
Build the opaque value mapping for the given conditional operator if it's the GNU ?
OpaqueValueMapping(CIRGenFunction &cgf, const OpaqueValueExpr *ov)
Build the opaque value mapping for an OpaqueValueExpr whose source expression is set to the expressio...
RunCleanupsScope(CIRGenFunction &cgf)
Enter a new cleanup scope.
void forceCleanup()
Force the emission of cleanups now, instead of waiting until this object is destroyed.
~RunCleanupsScope()
Exit this cleanup scope, emitting any accumulated cleanups.
void restore()
Can be used to restore the state early, before the dtor is run.
SourceLocRAIIObject(CIRGenFunction &cgf, mlir::Location value)
static bool isConstructorDelegationValid(const clang::CXXConstructorDecl *ctor)
Checks whether the given constructor is a valid subject for the complete-to-base constructor delegati...
static bool hasScalarEvaluationKind(clang::QualType type)
void emitOpenACCRoutine(const OpenACCRoutineDecl &d)
void emitLambdaDelegatingInvokeBody(const CXXMethodDecl *md)
mlir::Value emitComplexToScalarConversion(mlir::Value src, QualType srcTy, QualType dstTy, SourceLocation loc)
Emit a conversion from the specified complex type to the specified destination type,...
cir::CallOp emitCoroIDBuiltinCall(mlir::Location loc, mlir::Value nullPtr)
void emitCallArgs(CallArgList &args, PrototypeWrapper prototype, llvm::iterator_range< clang::CallExpr::const_arg_iterator > argRange, AbstractCallee callee=AbstractCallee(), unsigned paramsToSkip=0)
mlir::Type convertType(clang::QualType t)
cir::GlobalOp addInitializerToStaticVarDecl(const VarDecl &d, cir::GlobalOp gv, cir::GetGlobalOp gvAddr)
Add the initializer for 'd' to the global variable that has already been created for it.
mlir::Value emitCheckedArgForAssume(const Expr *e)
Emits an argument for a call to a __builtin_assume.
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())
void emitDeleteCall(const FunctionDecl *deleteFD, mlir::Value ptr, QualType deleteTy)
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.
void emitAnyExprToExn(const Expr *e, Address addr)
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)
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)
CleanupKind getCleanupKind(QualType::DestructionKind kind)
AggValueSlot::Overlap_t getOverlapForFieldInit(const FieldDecl *fd)
mlir::LogicalResult emitSimpleStmt(const clang::Stmt *s, bool useCurrentScope)
mlir::Operation * curFn
The current function or global initializer that is generated code for.
mlir::LogicalResult emitAsmStmt(const clang::AsmStmt &s)
Definition CIRGenAsm.cpp:86
mlir::Value emitScalarConversion(mlir::Value src, clang::QualType srcType, clang::QualType dstType, clang::SourceLocation loc)
Emit a conversion from the specified type to the specified destination type, both of which are CIR sc...
mlir::Value emitPromotedComplexExpr(const Expr *e, QualType promotionType)
ImplicitParamDecl * cxxStructorImplicitParamDecl
When generating code for a constructor or destructor, this will hold the implicit argument (e....
mlir::LogicalResult emitOpenACCComputeConstruct(const OpenACCComputeConstruct &s)
EHScopeStack ehStack
Tracks function scope overall cleanup handling.
void enterDtorCleanups(const CXXDestructorDecl *dtor, CXXDtorType type)
Enter the cleanups necessary to complete the given phase of destruction for a destructor.
mlir::Value emitUnPromotedValue(mlir::Value result, QualType unPromotionType)
cir::CallOp emitCoroEndBuiltinCall(mlir::Location loc, mlir::Value nullPtr)
mlir::LogicalResult emitSwitchBody(const clang::Stmt *s)
mlir::LogicalResult emitForStmt(const clang::ForStmt &s)
AggValueSlot createAggTemp(QualType ty, mlir::Location loc, const Twine &name="tmp", Address *alloca=nullptr)
Create a temporary memory object for the given aggregate type.
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)
void emitNewArrayInitializer(const CXXNewExpr *E, QualType ElementType, mlir::Type ElementTy, Address BeginPtr, mlir::Value NumElements, mlir::Value AllocSizeWithoutCookie)
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 emitCXXTemporary(const CXXTemporary *temporary, QualType tempType, Address ptr)
Emits all the code to cause the given temporary to be cleaned up.
LValue emitStringLiteralLValue(const StringLiteral *e, llvm::StringRef name=".str")
void maybeEmitDeferredVarDeclInit(const VarDecl *vd)
void emitVAEnd(mlir::Value vaList)
Emits the end of a CIR variable-argument operation (cir.va_start)
mlir::Value emitToMemory(mlir::Value value, clang::QualType ty)
Given a value and its clang type, returns the value casted to its memory representation.
mlir::LogicalResult emitOpenACCHostDataConstruct(const OpenACCHostDataConstruct &s)
LValue emitLValueForField(LValue base, const clang::FieldDecl *field)
mlir::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...
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.
bool needsEHCleanup(QualType::DestructionKind kind)
Determines whether an EH cleanup is required to destroy a type with the given destruction kind.
mlir::LogicalResult emitSwitchCase(const clang::SwitchCase &s, bool buildingTopLevelCase)
Address emitLoadOfReference(LValue refLVal, mlir::Location loc, LValueBaseInfo *pointeeBaseInfo)
Address getAddressOfDirectBaseInCompleteClass(mlir::Location loc, Address value, const CXXRecordDecl *derived, const CXXRecordDecl *base, bool baseIsVirtual)
Convert the given pointer to a complete class to the given direct base.
bool shouldNullCheckClassCastValue(const CastExpr *ce)
CIRGenBuilderTy & getBuilder()
void emitDecl(const clang::Decl &d, bool evaluateConditionDecl=false)
LValue emitBinaryOperatorLValue(const BinaryOperator *e)
mlir::Value emitOpenACCIntExpr(const Expr *intExpr)
Address getAddrOfBitFieldStorage(LValue base, const clang::FieldDecl *field, mlir::Type fieldType, unsigned index)
AggValueSlot::Overlap_t getOverlapForBaseInit(const CXXRecordDecl *rd, const CXXRecordDecl *baseRD, bool isVirtual)
Determine whether a base class initialization may overlap some other object.
void emitDestroy(Address addr, QualType type, Destroyer *destroyer)
Immediately perform the destruction of the given object.
const CIRGenModule & getCIRGenModule() const
void startFunction(clang::GlobalDecl gd, clang::QualType returnType, cir::FuncOp fn, cir::FuncType funcType, FunctionArgList args, clang::SourceLocation loc, clang::SourceLocation startLoc)
Emit code for the start of a function.
unsigned counterRefTmp
Hold counters for incrementally naming temporaries.
mlir::MLIRContext & getMLIRContext()
mlir::LogicalResult emitOpenACCEnterDataConstruct(const OpenACCEnterDataConstruct &s)
Destroyer * getDestroyer(clang::QualType::DestructionKind kind)
void Destroyer(CIRGenFunction &cgf, Address addr, QualType ty)
void emitDestructorBody(FunctionArgList &args)
Emits the body of the current destructor.
void emitAtomicInit(Expr *init, LValue dest)
LValue emitCastLValue(const CastExpr *e)
Casts are never lvalues unless that cast is to a reference type.
mlir::Value emitLoadOfScalar(LValue lvalue, SourceLocation loc)
EmitLoadOfScalar - Load a scalar value from an address, taking care to appropriately convert from the...
mlir::LogicalResult emitCXXTryStmt(const clang::CXXTryStmt &s)
bool containsLabel(const clang::Stmt *s, bool ignoreCaseStmts=false)
Return true if the statement contains a label in it.
DeclMapTy localDeclMap
This keeps track of the CIR allocas or globals for local C declarations.
mlir::Value createOpenACCConstantInt(mlir::Location loc, unsigned width, int64_t value)
LValue emitDeclRefLValue(const clang::DeclRefExpr *e)
void emitComplexExprIntoLValue(const Expr *e, LValue dest, bool isInit)
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)
LValue emitPredefinedLValue(const PredefinedExpr *e)
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.
void emitCXXDeleteExpr(const CXXDeleteExpr *e)
mlir::LogicalResult emitCoroutineBody(const CoroutineBodyStmt &s)
RValue emitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *e, const CXXMethodDecl *md, ReturnValueSlot returnValue)
mlir::LogicalResult emitCompoundStmt(const clang::CompoundStmt &s, Address *lastValue=nullptr, AggValueSlot slot=AggValueSlot::ignored())
void emitNullabilityCheck(LValue lhs, mlir::Value rhs, clang::SourceLocation loc)
Given an assignment *lhs = rhs, emit a test that checks if rhs is nonnull, if 1LHS is marked _Nonnull...
mlir::LogicalResult emitGotoStmt(const clang::GotoStmt &s)
void emitStoreThroughLValue(RValue src, LValue dst, bool isInit=false)
Store the specified rvalue into the specified lvalue, where both are guaranteed to the have the same ...
bool isLValueSuitableForInlineAtomic(LValue lv)
An LValue is a candidate for having its loads and stores be made atomic if we are operating under /vo...
mlir::LogicalResult emitStmt(const clang::Stmt *s, bool useCurrentScope, llvm::ArrayRef< const Attr * > attrs={})
void popCleanupBlocks(EHScopeStack::stable_iterator oldCleanupStackDepth)
Takes the old cleanup stack size and emits the cleanup blocks that have been added.
RValue getOrCreateOpaqueRValueMapping(const OpaqueValueExpr *e)
Given an opaque value expression, return its RValue mapping if it exists, otherwise create one.
Address createTempAllocaWithoutCast(mlir::Type ty, CharUnits align, mlir::Location loc, const Twine &name="tmp", mlir::Value arraySize=nullptr, mlir::OpBuilder::InsertPoint ip={})
This creates a alloca and inserts it into the entry block of the current region.
Address emitVAListRef(const Expr *e)
Build a "reference" to a va_list; this is either the address or the value of the expression,...
mlir::LogicalResult emitCompoundStmtWithoutScope(const clang::CompoundStmt &s, Address *lastValue=nullptr, AggValueSlot slot=AggValueSlot::ignored())
mlir::LogicalResult emitOpenACCExitDataConstruct(const OpenACCExitDataConstruct &s)
void emitIgnoredExpr(const clang::Expr *e)
Emit code to compute the specified expression, ignoring the result.
Address createMemTemp(QualType t, mlir::Location loc, const Twine &name="tmp", Address *alloca=nullptr, mlir::OpBuilder::InsertPoint ip={})
Create a temporary memory object of the given type, with appropriate alignmen and cast it to the defa...
void emitDelegatingCXXConstructorCall(const CXXConstructorDecl *ctor, const FunctionArgList &args)
mlir::Value emitDynamicCast(Address thisAddr, const CXXDynamicCastExpr *dce)
void emitAggExpr(const clang::Expr *e, AggValueSlot slot)
mlir::Value emitAlloca(llvm::StringRef name, mlir::Type ty, mlir::Location loc, clang::CharUnits alignment, mlir::OpBuilder::InsertPoint ip, mlir::Value arraySize=nullptr)
mlir::LogicalResult emitOpenACCAtomicConstruct(const OpenACCAtomicConstruct &s)
void popCleanupBlock()
Pops a cleanup block.
mlir::Value emitVAArg(VAArgExpr *ve)
Generate code to get an argument from the passed in pointer and update it accordingly.
RValue emitCXXPseudoDestructorExpr(const CXXPseudoDestructorExpr *expr)
LValue emitCompoundLiteralLValue(const CompoundLiteralExpr *e)
void emitAutoVarCleanups(const AutoVarEmission &emission)
RValue emitRotate(const CallExpr *e, bool isRotateLeft)
mlir::LogicalResult emitOpenACCLoopConstruct(const OpenACCLoopConstruct &s)
CIRGenCallee emitCallee(const clang::Expr *e)
Address emitAddrOfFieldStorage(Address base, const FieldDecl *field, llvm::StringRef fieldName, unsigned fieldIndex)
Get the address of a zero-sized field within a record.
This class organizes the cross-function state that is used while generating CIR code.
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
This class organizes the cross-module state that is used while lowering AST types to CIR types.
Definition CIRGenTypes.h:48
A saved depth on the scope stack.
A stack of scopes which respond to exceptions, including cleanups and catch blocks.
Type for representing both the decl and type of parameters to a function.
Definition CIRGenCall.h:191
static LValue makeAddr(Address address, clang::QualType t, LValueBaseInfo baseInfo)
This trivial value class is used to represent the result of an expression that is evaluated.
Definition CIRGenValue.h:33
Contains the address where the return value of a function can be stored, and whether the address is v...
Definition CIRGenCall.h:254
Represents a call to a C++ constructor.
Definition ExprCXX.h: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 delete expression for memory deallocation and destructor calls, e.g.
Definition ExprCXX.h:2628
Represents a C++ destructor within a class.
Definition DeclCXX.h:2869
A C++ dynamic_cast expression (C++ [expr.dynamic.cast]).
Definition ExprCXX.h:481
CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for statement, represented as 'for (ra...
Definition StmtCXX.h:135
Represents a call to a member function that may be written either with member call syntax (e....
Definition ExprCXX.h:179
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2129
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)".
Definition ExprCXX.h:2357
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:2747
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
Represents a C++ temporary.
Definition ExprCXX.h:1460
A C++ throw-expression (C++ [except.throw]).
Definition ExprCXX.h:1209
CXXTryStmt - A C++ try block, including all handlers.
Definition StmtCXX.h:69
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2877
CaseStmt - Represent a case statement.
Definition Stmt.h: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 body of a coroutine.
Definition StmtCXX.h:320
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:3160
ForStmt - This represents a 'for (init;cond;inc)' stmt.
Definition Stmt.h:2888
Represents a function declaration or definition.
Definition Decl.h:2000
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5266
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:524
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:4922
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition Expr.h:3298
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
ObjCMethodDecl - Represents an instance or class method declaration.
Definition DeclObjC.h:140
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Definition Expr.h:1178
Expr * getSourceExpr() const
The source expression of an opaque value expression is the expression which originally generated the ...
Definition Expr.h:1228
Represents a parameter to a function.
Definition Decl.h:1790
[C99 6.4.2.2] - A predefined identifier such as func.
Definition Expr.h:2005
A (possibly-)qualified type.
Definition TypeBase.h:937
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition TypeBase.h:8330
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:3513
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition Expr.h:2244
Represents a call to the builtin function __builtin_va_arg.
Definition Expr.h:4891
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition Decl.h:712
Represents a variable declaration or definition.
Definition Decl.h:926
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.
@ NormalCleanup
Denotes a cleanup that should run when a scope is exited using normal control flow (falling off the e...
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const AstTypeMatcher< ArrayType > arrayType
const internal::VariadicAllOfMatcher< Stmt > stmt
Matches statements.
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
CXXCtorType
C++ constructor types.
Definition ABI.h:24
OpenACCDirectiveKind
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
OpenACCComputeConstruct(OpenACCDirectiveKind K, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses, Stmt *StructuredBlock)
const FunctionProtoType * T
CXXDtorType
C++ destructor types.
Definition ABI.h:34
#define true
Definition stdbool.h:25
static bool aggValueSlot()
static bool peepholeProtection()
static bool opAllocaEscapeByReference()
static bool generateDebugInfo()
AutoVarEmission(const clang::VarDecl &variable)
bool isEscapingByRef
True if the variable is a __block variable that is captured by an escaping block.
Address addr
The address of the alloca for languages with explicit address space (e.g.
bool emittedAsOffload
True if the variable was emitted as an offload recipe, and thus doesn't have the same sort of alloca ...
bool isConstantAggregate
True if the variable is of aggregate type and has a constant initializer.
Address getAllocatedAddress() const
Returns the raw, allocated address, which is not necessarily the address of the object itself.
Address getObjectAddress(CIRGenFunction &cgf) const
Returns the address of the object within this declaration.
std::unique_ptr< CGCoroData > data
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