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