18#include "mlir/IR/Location.h"
20#include "clang/AST/Attrs.inc"
47 mlir::OpBuilder::InsertPoint ip) {
61 "emitAutoVarAlloca: decl escaping by reference");
85 getContext().getBaseElementType(ty)->isObjCObjectPointerType()) &&
99 (
cgm.getCodeGenOpts().MergeAllConstants && !nrvo &&
119 if (
const auto *cxxrd = dyn_cast<CXXRecordDecl>(rd);
120 (cxxrd && !cxxrd->hasTrivialDestructor()) ||
121 rd->isNonTrivialToPrimitiveDestroy()) {
126 cir::ConstantOp falseNVRO = builder.getFalse(loc);
130 assert(builder.getInsertionBlock());
131 builder.createStore(loc, falseNVRO, nrvoFlag);
143 nullptr,
nullptr, ip);
163 cgm.getDataLayout().getAlignment(defaultTy,
false));
166 mlir::Value v = builder.createStackSave(loc, defaultTy);
168 builder.createStore(loc, v, stack);
183 nullptr, builder.saveInsertionPoint());
191 emission.
addr = address;
211 if (constructor->isTrivial() && constructor->isDefaultConstructor() &&
212 !construct->requiresZeroInitialization())
221 mlir::TypedAttr constant) {
222 mlir::Type ty = constant.getType();
243 mlir::Location loc = builder.getUnknownLoc();
257 assert(emission.
variable &&
"emission was not valid!");
273 if (!init &&
type.isNonTrivialToPrimitiveDefaultInitialize() ==
276 "emitAutoVarInit: non-trivial to default initialize");
291 : (d.
getAttr<UninitializedAttr>()
295 auto initializeWhatIsTechnicallyUninitialized = [&](
Address addr) {
296 if (trivialAutoVarInit ==
304 initializeWhatIsTechnicallyUninitialized(addr);
308 mlir::Attribute constant;
317 if (constant && !mlir::isa<cir::ZeroAttr>(constant) &&
318 (trivialAutoVarInit !=
330 initializeWhatIsTechnicallyUninitialized(addr);
338 assert(addr.
isValid() &&
"Should have an address");
340 assert(allocaOp &&
"Address should come straight out of the alloca");
342 if (!allocaOp.use_empty())
350 auto typedConstant = mlir::dyn_cast<mlir::TypedAttr>(constant);
351 assert(typedConstant &&
"expected typed attribute");
355 assert(init &&
"expected initializer");
359 RValue::get(builder.getConstant(initLoc, typedConstant)), lv);
405 "emitLoopConditionVariable: OpenCL local address space");
407 CIRGenFunction::VarDeclContext varDeclCtx{*
this, &d};
427 builder.getBoolTy(),
CharUnits::One(), loc,
"cond.cleanup.isactive",
430 builder.createFlagStore(loc,
false, activeFlag.
getPointer());
438 builder.createFlagStore(loc,
true, activeFlag.
getPointer());
465 cir::GlobalLinkageKind linkage =
cgm.getCIRLinkageVarDefinition(&d);
479 CIRGenFunction::VarDeclContext varDeclCtx{*
this, &d};
489 std::string contextName;
491 if (
auto *cd = dyn_cast<CapturedDecl>(dc))
493 if (
const auto *fd = dyn_cast<FunctionDecl>(dc))
497 "getStaticDeclName: block decl context for static var");
500 "getStaticDeclName: ObjC decl context for static var");
503 "getStaticDeclName: Unknown context for static var decl");
513 cir::GlobalLinkageKind linkage) {
534 mlir::Attribute init =
nullptr;
536 d.
hasAttr<CUDASharedAttr>() || d.
hasAttr<LoaderUninitializedAttr>())
537 init = cir::UndefAttr::get(lty);
546 lty,
false, linkage, addrSpace);
550 gv.setInitialValueAttr(init);
551 gv.setAlignment(
getASTContext().getDeclAlign(&d).getAsAlign().value());
586 if (
const auto *cd = dyn_cast<CXXConstructorDecl>(dc))
588 else if (
const auto *dd = dyn_cast<CXXDestructorDecl>(dc))
590 else if (
const auto *fd = dyn_cast<FunctionDecl>(dc))
602 "OpenMP: DisableAutoDeclareTargetRAII for static local");
611 mlir::Attribute constAttr,
613 auto functionName = [&](
const DeclContext *dc) -> std::string {
614 if (
const auto *fd = dyn_cast<FunctionDecl>(dc)) {
615 if (
const auto *cc = dyn_cast<CXXConstructorDecl>(fd))
616 return cc->getNameAsString();
617 if (
const auto *cd = dyn_cast<CXXDestructorDecl>(fd))
618 return cd->getNameAsString();
620 }
else if (
const auto *om = dyn_cast<ObjCMethodDecl>(dc)) {
621 return om->getNameAsString();
627 llvm_unreachable(
"expected a function or method");
634 if (!cacheEntry || cacheEntry.getInitialValue() != constAttr) {
635 auto ty = mlir::cast<mlir::TypedAttr>(constAttr).getType();
636 bool isConstant =
true;
642 name = (
"__const." + functionName(dc) +
"." + d.
getName()).str();
644 llvm_unreachable(
"local variable has no parent function or method");
647 cir::GlobalOp gv = builder.createVersionedGlobal(
649 cir::GlobalLinkageKind::PrivateLinkage);
653 cir::GlobalLinkageKind::PrivateLinkage));
654 gv.setInitialValueAttr(constAttr);
655 gv.setAlignment(align.getAsAlign().value());
659 }
else if (cacheEntry.getAlignment() < align.getQuantity()) {
660 cacheEntry.setAlignment(align.getAsAlign().value());
665 mlir::Type eltTy = mlir::cast<mlir::TypedAttr>(constAttr).getType();
666 auto ptrTy = builder.getPointerTo(cacheEntry.getSymType());
667 mlir::Value globalPtr = cir::GetGlobalOp::create(
669 return Address(globalPtr, eltTy, align);
676 const VarDecl &d, cir::GlobalOp gv, cir::GetGlobalOp gvAddr) {
678 mlir::TypedAttr init = mlir::dyn_cast_if_present<mlir::TypedAttr>(
686 "constant l-value expression");
692 gv.setConstant(
false);
694 gvAddr.setStaticLocal(
true);
708 if (gv.getSymType() != init.getType()) {
709 gv.setSymType(init.getType());
717 gvAddr.getAddr().setType(builder.getPointerTo(init.getType()));
725 gv.setInitialValueAttr(init);
734 gvAddr.setStaticLocal(
true);
741 cir::GlobalLinkageKind linkage) {
745 cir::GlobalOp globalOp =
cgm.getOrCreateStaticVarDecl(d, linkage);
750 auto getAddrOp = addr.getDefiningOp<cir::GetGlobalOp>();
751 assert(getAddrOp &&
"expected cir::GetGlobalOp");
767 mlir::Type expectedType = addr.getType();
769 cir::GlobalOp var = globalOp;
777 var.setAlignment(alignment.
getAsAlign().value());
782 cgm.addGlobalAnnotations(&d, var);
783 if (d.
getAttr<PragmaClangBSSSectionAttr>())
785 "emitStaticVarDecl: CIR global BSS section attribute");
786 if (d.
getAttr<PragmaClangDataSectionAttr>())
788 "emitStaticVarDecl: CIR global Data section attribute");
789 if (d.
getAttr<PragmaClangRodataSectionAttr>())
791 "emitStaticVarDecl: CIR global Rodata section attribute");
792 if (d.
getAttr<PragmaClangRelroSectionAttr>())
794 "emitStaticVarDecl: CIR global Relro section attribute");
796 if (
const SectionAttr *sa = d.
getAttr<SectionAttr>())
797 var.setSectionAttr(builder.getStringAttr(sa->getName()));
799 if (
cgm.getCodeGenOpts().KeepPersistentStorageVariables)
808 mlir::Value castedAddr =
809 builder.createBitcast(getAddrOp.getAddr(), expectedType);
811 cgm.setStaticLocalDeclAddress(&d, var);
818 bool capturedByInit) {
823 if (capturedByInit) {
832 LValue lvalue,
bool capturedByInit) {
834 if (capturedByInit) {
841 if (
type->isReferenceType()) {
856 "emitExprAsInit: complex type captured by init");
871 llvm_unreachable(
"bad evaluation kind");
876 case Decl::BuiltinTemplate:
877 case Decl::TranslationUnit:
878 case Decl::ExternCContext:
879 case Decl::Namespace:
880 case Decl::UnresolvedUsingTypename:
881 case Decl::ClassTemplateSpecialization:
882 case Decl::ClassTemplatePartialSpecialization:
883 case Decl::VarTemplateSpecialization:
884 case Decl::VarTemplatePartialSpecialization:
885 case Decl::TemplateTypeParm:
886 case Decl::UnresolvedUsingValue:
887 case Decl::NonTypeTemplateParm:
888 case Decl::CXXDeductionGuide:
889 case Decl::CXXMethod:
890 case Decl::CXXConstructor:
891 case Decl::CXXDestructor:
892 case Decl::CXXConversion:
894 case Decl::MSProperty:
895 case Decl::IndirectField:
897 case Decl::ObjCAtDefsField:
899 case Decl::ImplicitParam:
900 case Decl::ClassTemplate:
901 case Decl::VarTemplate:
902 case Decl::FunctionTemplate:
903 case Decl::TypeAliasTemplate:
904 case Decl::TemplateTemplateParm:
905 case Decl::ObjCMethod:
906 case Decl::ObjCCategory:
907 case Decl::ObjCProtocol:
908 case Decl::ObjCInterface:
909 case Decl::ObjCCategoryImpl:
910 case Decl::ObjCImplementation:
911 case Decl::ObjCProperty:
912 case Decl::ObjCCompatibleAlias:
913 case Decl::PragmaComment:
914 case Decl::PragmaDetectMismatch:
915 case Decl::AccessSpec:
916 case Decl::LinkageSpec:
918 case Decl::ObjCPropertyImpl:
919 case Decl::FileScopeAsm:
921 case Decl::FriendTemplate:
923 case Decl::OutlinedFunction:
925 case Decl::UsingShadow:
926 case Decl::ConstructorUsingShadow:
927 case Decl::ObjCTypeParam:
929 case Decl::UnresolvedUsingIfExists:
930 case Decl::HLSLBuffer:
931 case Decl::HLSLRootSignature:
932 llvm_unreachable(
"Declaration should not be in declstmts!");
935 case Decl::EnumConstant:
936 case Decl::ExplicitInstantiation:
937 case Decl::StaticAssert:
941 case Decl::TemplateParamObject:
944 case Decl::LifetimeExtendedTemporary:
945 case Decl::RequiresExprBody:
946 case Decl::UnnamedGlobalConstant:
952 case Decl::CXXRecord:
953 case Decl::NamespaceAlias:
955 case Decl::UsingEnum:
956 case Decl::UsingDirective:
960 case Decl::Decomposition: {
963 "Should not see file-scope variables inside a function!");
965 if (evaluateConditionDecl)
969 case Decl::OpenACCDeclare:
972 case Decl::OpenACCRoutine:
975 case Decl::OMPThreadPrivate:
978 case Decl::OMPGroupPrivate:
981 case Decl::OMPAllocate:
984 case Decl::OMPCapturedExpr:
987 case Decl::OMPRequires:
990 case Decl::OMPDeclareMapper:
993 case Decl::OMPDeclareReduction:
997 case Decl::TypeAlias: {
1004 case Decl::ImplicitConceptSpecialization:
1005 case Decl::TopLevelStmt:
1006 case Decl::UsingPack:
1007 case Decl::CXXExpansionStmt:
1009 std::string(
"emitDecl: unhandled decl type: ") +
1016 if (!
sanOpts.has(SanitizerKind::NullabilityAssign))
1026 : addr(addr),
type(
type), destroyer(destroyer) {
1041 DestroyNRVOVariable(Address addr, QualType
type, mlir::Value nrvoFlag)
1042 : nrvoFlag(nrvoFlag), addr(addr), ty(
type) {}
1044 mlir::Value nrvoFlag;
1048 void emit(CIRGenFunction &cgf, Flags flags)
override {
1050 bool nrvo = flags.isForNormalCleanup() && nrvoFlag;
1053 mlir::OpBuilder::InsertionGuard guard(builder);
1056 mlir::Location loc = addr.
getPointer().getLoc();
1058 mlir::Value notNRVO = builder.
createNot(didNRVO);
1059 cir::IfOp::create(builder, loc, notNRVO,
false,
1060 [&](mlir::OpBuilder &b, mlir::Location) {
1061 static_cast<Derived *
>(
this)->emitDestructorCall(cgf);
1065 static_cast<Derived *
>(
this)->emitDestructorCall(cgf);
1069 virtual ~DestroyNRVOVariable() =
default;
1072struct DestroyNRVOVariableCXX final
1073 : DestroyNRVOVariable<DestroyNRVOVariableCXX> {
1074 DestroyNRVOVariableCXX(Address addr, QualType
type,
1075 const CXXDestructorDecl *dtor, mlir::Value nrvoFlag)
1076 : DestroyNRVOVariable<DestroyNRVOVariableCXX>(addr,
type, nrvoFlag),
1079 const CXXDestructorDecl *dtor;
1081 void emitDestructorCall(CIRGenFunction &cgf) {
1090 CallStackRestore(Address stack) : stack(stack) {}
1092 void emit(CIRGenFunction &cgf, Flags flags)
override {
1093 mlir::Location loc = stack.getPointer().getLoc();
1102 mlir::Value arrayBegin;
1104 QualType elementType;
1105 CharUnits elementAlign;
1108 IrregularPartialArrayDestroy(mlir::Value arrayBegin, Address arrayEndPointer,
1109 QualType elementType, CharUnits elementAlign,
1111 : arrayBegin(arrayBegin), arrayEndPointer(arrayEndPointer),
1112 elementType(elementType), elementAlign(elementAlign),
1113 destroyer(destroyer) {}
1115 void emit(CIRGenFunction &cgf, Flags flags)
override {
1117 mlir::Location loc = arrayBegin.getLoc();
1119 mlir::Value arrayEnd = builder.
createLoad(loc, arrayEndPointer);
1126 cir::PointerType ptrToElmType = builder.
getPointerTo(cirElementType);
1128 mlir::Value begin = arrayBegin;
1129 if (baseElementType != elementType) {
1138 cir::CmpOp::create(builder, loc, cir::CmpOpKind::ne, arrayEnd, begin);
1140 builder, loc, ne,
false,
1141 [&](mlir::OpBuilder &b, mlir::Location loc) {
1148 [&](mlir::OpBuilder &b, mlir::Location loc) {
1149 mlir::Value cur = builder.
createLoad(loc, iterAddr);
1150 mlir::Value cmp = cir::CmpOp::create(
1151 builder, loc, cir::CmpOpKind::ne, cur, begin);
1155 [&](mlir::OpBuilder &b, mlir::Location loc) {
1156 mlir::Value cur = builder.
createLoad(loc, iterAddr);
1158 loc, mlir::cast<cir::IntType>(cgf.
ptrDiffTy), -1);
1159 mlir::Value prev = cir::PtrStrideOp::create(
1160 builder, loc, ptrToElmType, cur, negOne);
1163 destroyer(cgf, elemAddr, baseElementType);
1183 ehStack.pushCleanup<IrregularPartialArrayDestroy>(
1184 EHCleanup, arrayBegin, arrayEndPointer, elementType, elementAlign,
1203 assert(dtorKind &&
"cannot push destructor for trivial type");
1216 assert(dtorKind &&
"cannot push destructor for trivial type");
1225 bool useEHCleanupForArray) {
1234 bool useEHCleanupForArray) {
1236 cgm.errorNYI(
"conditional lifetime-extended destroy");
1243 useEHCleanupForArray);
1270 mlir::Value numElements,
1279 cir::PointerType ptrToElmType = builder.getPointerTo(cirElementType);
1281 auto regionBuilder = [&](mlir::OpBuilder &b, mlir::Location loc) {
1282 mlir::BlockArgument arg =
1283 b.getInsertionBlock()->addArgument(ptrToElmType, loc);
1288 destroyer(*
this, curAddr, elementType);
1290 cir::YieldOp::create(b, loc);
1294 if (
auto constantCount = numElements.getDefiningOp<cir::ConstantOp>()) {
1296 if (
auto constIntAttr = constantCount.getValueAttr<cir::IntAttr>())
1297 size = constIntAttr.getUInt();
1298 auto arrayTy = cir::ArrayType::get(cirElementType, size);
1299 mlir::Value arrayOp = builder.createPtrBitcast(begin, arrayTy);
1306 mlir::Value elemBegin = builder.createPtrBitcast(begin, cirElementType);
1307 cir::ArrayDtor::create(builder,
getLoc(*
currSrcLoc), elemBegin, numElements,
1322 return destroyer(*
this, addr,
type);
1330 auto constantCount =
length.getDefiningOp<cir::ConstantOp>();
1331 if (constantCount) {
1332 auto constIntAttr = mlir::dyn_cast<cir::IntAttr>(constantCount.getValue());
1333 if (constIntAttr && constIntAttr.getUInt() == 0)
1342 if (constantCount && constantCount.use_empty())
1343 constantCount.erase();
1350 llvm_unreachable(
"no destroyer for trivial dtor");
1356 cgm.errorNYI(
"getDestroyer: other destruction kind");
1359 llvm_unreachable(
"Unknown DestructionKind");
1363 ehStack.pushCleanup<CallStackRestore>(
kind, spMem);
1384 llvm_unreachable(
"no cleanup for trivially-destructible variable");
1390 assert(!
type->isArrayType());
1392 ehStack.pushCleanup<DestroyNRVOVariableCXX>(cleanupKind, addr,
type, dtor,
1402 cgm.errorNYI(var->getSourceRange(),
1403 "emitAutoVarTypeCleanup: other dtor kind");
1412 ehStack.pushCleanup<DestroyObject>(cleanupKind, addr,
type, destroyer);
1416 if (
auto *dd = dyn_cast_if_present<DecompositionDecl>(vd)) {
1417 for (
auto *b : dd->flat_bindings())
1418 if (
auto *hd = b->getHoldingVar())
1424 if (!shouldEmitLifetimeMarkers)
1427 assert(mlir::cast<cir::PointerType>(addr.getType()).getAddrSpace() ==
1429 "Pointer should be in alloca address space");
1431 cir::LifetimeStartOp::create(builder, loc, addr);
1436 if (!shouldEmitLifetimeMarkers)
1439 assert(mlir::cast<cir::PointerType>(addr.getType()).getAddrSpace() ==
1441 "Pointer should be in alloca address space");
1443 cir::LifetimeEndOp::create(builder, loc, addr);
static void emit(Program &P, llvm::SmallVectorImpl< std::byte > &Code, const T &Val, bool &Success)
Helper to write bytecode and bail out if 32-bit offsets become invalid.
static bool isRedundantBeforeReturn(mlir::Region &cleanupRegion)
static void emitStoresForConstant(CIRGenModule &cgm, const VarDecl &d, Address addr, bool isVolatile, CIRGenBuilderTy &builder, mlir::TypedAttr constant)
static std::string getStaticDeclName(CIRGenModule &cgm, const VarDecl &d)
This file defines OpenACC nodes for declarative directives.
static constexpr bool needsDtor()
Defines the clang::Expr interface and subclasses for C++ expressions.
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
cir::ConditionOp createCondition(mlir::Value condition)
Create a loop condition.
cir::ConstantOp getConstant(mlir::Location loc, mlir::TypedAttr attr)
cir::PointerType getPointerTo(mlir::Type ty)
cir::DoWhileOp createDoWhile(mlir::Location loc, llvm::function_ref< void(mlir::OpBuilder &, mlir::Location)> condBuilder, llvm::function_ref< void(mlir::OpBuilder &, mlir::Location)> bodyBuilder)
Create a do-while operation.
mlir::Value createPtrBitcast(mlir::Value src, mlir::Type newPointeeTy)
mlir::Value createNot(mlir::Location loc, mlir::Value value)
cir::YieldOp createYield(mlir::Location loc, mlir::ValueRange value={})
Create a yield operation.
cir::LoadOp createFlagLoad(mlir::Location loc, mlir::Value addr)
Emit a load from an boolean flag variable.
llvm::TypeSize getTypeAllocSize(mlir::Type ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
const LangOptions & getLangOpts() const
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
CharUnits getDeclAlign(const Decl *D, bool ForAlignof=false) const
Return a conservative estimate of the alignment of the specified decl D.
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
mlir::Value getPointer() const
mlir::Type getElementType() const
Address withElementType(CIRGenBuilderTy &builder, mlir::Type ElemTy) const
Return address with different element type, a bitcast pointer, and the same alignment.
clang::CharUnits getAlignment() const
cir::AllocaOp getUnderlyingAllocaOp() const
Return the underlying alloca for this address, if any.
static AggValueSlot forLValue(const LValue &LV, IsDestructed_t isDestructed, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed)
cir::LoadOp createLoad(mlir::Location loc, Address addr, bool isVolatile=false, bool isNontemporal=false)
cir::StoreOp createStore(mlir::Location loc, mlir::Value val, Address dst, bool isVolatile=false, bool isNontemporal=false, mlir::IntegerAttr align={}, cir::SyncScopeKindAttr scope={}, cir::MemOrderAttr order={})
cir::StackRestoreOp createStackRestore(mlir::Location loc, mlir::Value v)
cir::ConstantOp getConstInt(mlir::Location loc, llvm::APSInt intVal)
An RAII class that suppresses cir.cleanup.scope creation for cleanups pushed onto the EH stack while ...
Captures cleanups for a loop's condition variable so that they can be emitted into the loop op's per-...
void emitOpenACCRoutine(const OpenACCRoutineDecl &d)
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.
static cir::TypeEvaluationKind getEvaluationKind(clang::QualType type)
Return the cir::TypeEvaluationKind of QualType type.
AutoVarEmission emitAutoVarAlloca(const clang::VarDecl &d, mlir::OpBuilder::InsertPoint ip={})
void emitAutoVarTypeCleanup(const AutoVarEmission &emission, clang::QualType::DestructionKind dtorKind)
Enter a destroy cleanup for the given local variable.
void emitVariablyModifiedType(QualType ty)
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,...
mlir::Block * getCurFunctionEntryBlock()
bool isInConditionalBranch() const
void emitOMPRequiresDecl(const OMPRequiresDecl &d)
VlaSizePair getVLASize(const VariableArrayType *type)
Returns an MLIR::Value+QualType pair that corresponds to the size, in non-variably-sized elements,...
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.
bool isTrivialInitializer(const Expr *init)
Determine whether the given initializer is trivial in the sense that it requires no code to be genera...
void emitOpenACCDeclare(const OpenACCDeclareDecl &d)
void pushIrregularPartialArrayCleanup(mlir::Value arrayBegin, Address arrayEndPointer, QualType elementType, CharUnits elementAlign, Destroyer *destroyer)
Push an EH cleanup to destroy already-constructed elements of the given array.
void emitLifetimeEndOp(mlir::Location loc, mlir::Value addr)
void pushCleanupAndDeferDeactivation(CleanupKind kind, As... a)
Push a cleanup and record it for deferred deactivation.
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
void emitLoopConditionVariable(const clang::VarDecl &d, DeferredLoopConditionCleanup &condCleanup)
Emit a loop's condition-variable declaration.
void emitOMPDeclareReduction(const OMPDeclareReductionDecl &d)
void emitExprAsInit(const clang::Expr *init, const clang::ValueDecl *d, LValue lvalue, bool capturedByInit=false)
Emit an expression as an initializer for an object (variable, field, etc.) at the given location.
void emitCXXGuardedInit(const VarDecl &varDecl, cir::GlobalOp globalOp, bool performInit)
Emit a guarded initializer for a static local variable.
mlir::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...
RValue emitReferenceBindingToExpr(const Expr *e)
Emits a reference binding to the passed in expression.
void pushDestroyAndDeferDeactivation(QualType::DestructionKind dtorKind, Address addr, QualType type)
void emitScalarInit(const clang::Expr *init, LValue lvalue, bool capturedByInit=false)
CleanupKind getCleanupKind(QualType::DestructionKind kind)
void emitOMPAllocateDecl(const OMPAllocateDecl &d)
void emitOMPDeclareMapper(const OMPDeclareMapperDecl &d)
EHScopeStack ehStack
Tracks function scope overall cleanup handling.
clang::SanitizerSet sanOpts
Sanitizers enabled for this function.
mlir::Type convertTypeForMem(QualType t)
void pushDestroy(QualType::DestructionKind dtorKind, Address addr, QualType type)
Push the standard destructor for the given type as at least a normal cleanup.
void emitVarDecl(const clang::VarDecl &d)
This method handles emission of any variable declaration inside a function, including static vars etc...
static Destroyer destroyCXXObject
Address returnValue
The temporary alloca to hold the return value.
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.
void initFullExprCleanupWithFlag(Address activeFlag)
void emitStoreOfComplex(mlir::Location loc, mlir::Value v, LValue dest, bool isInit)
EmitStoreOfComplex - Store a complex number into the specified l-value.
bool haveInsertPoint() const
True if an insertion point is defined.
void emitAutoVarInit(const AutoVarEmission &emission)
Emit the initializer for an allocated variable.
void maybeEmitDeferredVarDeclInit(const VarDecl *vd)
mlir::Value emitScalarExpr(const clang::Expr *e, bool ignoreResultAssign=false)
Emit the computation of the specified expression of scalar type.
void pushStackRestore(CleanupKind kind, Address spMem)
void emitAutoVarDecl(const clang::VarDecl &d)
Emit code and set up symbol table for a variable declaration with auto, register, or no storage class...
bool needsEHCleanup(QualType::DestructionKind kind)
Determines whether an EH cleanup is required to destroy a type with the given destruction kind.
CIRGenBuilderTy & getBuilder()
bool didCallStackSave
Whether a cir.stacksave operation has been added.
void emitDecl(const clang::Decl &d, bool evaluateConditionDecl=false)
void emitDestroy(Address addr, QualType type, Destroyer *destroyer)
Immediately perform the destruction of the given object.
void pushPendingCleanupToEHStack(const PendingCleanupEntry &entry)
Promote a single pending cleanup entry onto the EH scope stack.
llvm::DenseMap< const VarDecl *, mlir::Value > nrvoFlags
A mapping from NRVO variables to the flags used to indicate when the NRVO has been applied to this va...
mlir::MLIRContext & getMLIRContext()
Destroyer * getDestroyer(clang::QualType::DestructionKind kind)
void Destroyer(CIRGenFunction &cgf, Address addr, QualType ty)
std::optional< SourceRange > currSrcLoc
Use to track source locations across nested visitor traversals.
DeclMapTy localDeclMap
This keeps track of the CIR allocas or globals for local C declarations.
void pushEHDestroyIfNeeded(QualType::DestructionKind dtorKind, Address addr, QualType type)
pushEHDestroyIfNeeded - Push the standard destructor for the given type as an EH-only cleanup.
void emitOMPThreadPrivateDecl(const OMPThreadPrivateDecl &d)
void emitOMPGroupPrivateDecl(const OMPGroupPrivateDecl &d)
bool emitLifetimeStartOp(mlir::Location loc, mlir::Value addr)
LValue makeAddrLValue(Address addr, QualType ty, AlignmentSource source=AlignmentSource::Type)
void emitCXXDestructorCall(const CXXDestructorDecl *dd, CXXDtorType type, bool forVirtualBase, bool delegating, Address thisAddr, QualType thisTy)
void pushFullExprCleanup(CleanupKind kind, As... a)
Push a cleanup to be run at the end of the current full-expression.
clang::ASTContext & getContext() const
void setAddrOfLocalVar(const clang::VarDecl *vd, Address addr)
Set the address of a local variable.
void pushCleanupAfterFullExpr(CleanupKind kind, Address addr, QualType type, Destroyer *destroyer)
Queue a cleanup to be pushed after finishing the current full-expression.
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...
void emitOMPCapturedExpr(const OMPCapturedExprDecl &d)
void emitStoreThroughLValue(RValue src, LValue dst, bool isInit=false)
Store the specified rvalue into the specified lvalue, where both are guaranteed to the have the same ...
void pushLifetimeExtendedDestroy(CleanupKind kind, Address addr, QualType type, Destroyer *destroyer, bool useEHCleanupForArray)
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.
void emitAggExpr(const clang::Expr *e, AggValueSlot slot)
void emitAutoVarCleanups(const AutoVarEmission &emission)
This class organizes the cross-function state that is used while generating CIR code.
llvm::StringRef getMangledName(clang::GlobalDecl gd)
cir::GlobalOp getOrCreateStaticVarDecl(const VarDecl &d, cir::GlobalLinkageKind linkage)
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
clang::ASTContext & getASTContext() const
void insertGlobalSymbol(mlir::Operation *op)
mlir::Type convertType(clang::QualType type)
llvm::DenseMap< const VarDecl *, cir::GlobalOp > initializerConstants
void setGVProperties(mlir::Operation *op, const NamedDecl *d) const
Set visibility, dllimport/dllexport and dso_local.
static mlir::SymbolTable::Visibility getMLIRVisibilityFromCIRLinkage(cir::GlobalLinkageKind GLK)
void setTLSMode(mlir::Operation *op, const VarDecl &d, bool isExtendingDecl=false)
Set TLS mode for the given operation based on the given variable declaration.
const clang::LangOptions & getLangOpts() const
void setStaticLocalDeclAddress(const VarDecl *d, cir::GlobalOp c)
mlir::Location getLoc(clang::SourceLocation cLoc)
Helpers to convert the presumed location of Clang's SourceLocation to an MLIR Location.
mlir::ModuleOp getModule() const
bool supportsCOMDAT() const
mlir::MLIRContext & getMLIRContext()
mlir::Operation * getAddrOfGlobal(clang::GlobalDecl gd, ForDefinition_t isForDefinition=NotForDefinition)
cir::GlobalOp getStaticLocalDeclAddress(const VarDecl *d)
Address createUnnamedGlobalFrom(const VarDecl &d, mlir::Attribute constAttr, CharUnits align)
mlir::Type convertTypeForMem(clang::QualType, bool forBitField=false)
Convert type T into an mlir::Type.
void finalize(cir::GlobalOp gv)
mlir::Attribute tryEmitForInitializer(const VarDecl &d)
Try to emit the initializer of the given declaration as an abstract constant.
mlir::Attribute tryEmitAbstractForInitializer(const VarDecl &d)
Try to emit the initializer of the given declaration as an abstract constant.
A cleanup scope which generates the cleanup blocks lazily.
void setTestFlagInEHCleanup(bool value)
void setTestFlagInNormalCleanup(bool value)
bool isNormalCleanup() const
void setActiveFlag(Address var)
Information for lazily generating a cleanup.
Address getAddress() const
This trivial value class is used to represent the result of an expression that is evaluated.
static RValue get(mlir::Value v)
Represents a call to a C++ constructor.
Represents a C++ constructor within a class.
Represents a C++ destructor within a class.
CharUnits - This is an opaque type for sizes expressed in character units.
llvm::Align getAsAlign() const
getAsAlign - Returns Quantity as a valid llvm::Align, Beware llvm::Align assumes power of two 8-bit b...
static CharUnits One()
One - Construct a CharUnits quantity of one.
CharUnits alignmentOfArrayElement(CharUnits elementSize) const
Given that this is the alignment of the first element of an array, return the minimum alignment of an...
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
const DeclContext * getParentFunctionOrMethod(bool LexicalParent=false) const
If this decl is defined inside a function/method/block it returns the corresponding DeclContext,...
Decl * getNonClosureContext()
Find the innermost non-closure ancestor of this declaration, walking up through blocks,...
SourceLocation getLocation() const
const char * getDeclKindName() const
DeclContext * getDeclContext()
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
This represents one expression.
bool isConstantInitializer(ASTContext &Ctx, bool ForRef=false, const Expr **Culprit=nullptr) const
Returns true if this expression can be emitted to IR as a constant, and thus can be used as a constan...
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
GlobalDecl - represents a global declaration.
const Decl * getDecl() const
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
std::string getNameAsString() const
Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...
bool isExternallyVisible() const
A (possibly-)qualified type.
@ DK_objc_strong_lifetime
@ PDIK_Struct
The type is a struct containing a field whose type is not PCK_Trivial.
LangAS getAddressSpace() const
Return the address space of this type.
bool isConstantStorage(const ASTContext &Ctx, bool ExcludeCtor, bool ExcludeDtor)
bool isPODType(const ASTContext &Context) const
Determine whether this is a Plain Old Data (POD) type (C++ 3.9p10).
Represents a struct/union/class.
Encodes a location in the source.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
bool isConstantSizeType() const
Return true if this is not a variable sized type, according to the rules of C99 6....
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
bool isVectorType() const
bool isRecordType() const
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
TLSKind getTLSKind() const
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
bool hasFlexibleArrayInit(const ASTContext &Ctx) const
Whether this variable has a flexible array member initialized with one or more elements.
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
bool mightBeUsableInConstantExpressions(const ASTContext &C) const
Determine whether this variable's value might be usable in a constant expression, according to the re...
bool isNRVOVariable() const
Determine whether this local variable can be used with the named return value optimization (NRVO).
QualType::DestructionKind needsDestruction(const ASTContext &Ctx) const
Would the destruction of this variable have any effect, and if so, what kind?
const Expr * getInit() const
bool hasExternalStorage() const
Returns true if a variable has extern or private_extern storage.
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
@ TLS_None
Not a TLS variable.
bool isLocalVarDecl() const
Returns true for local variable declarations other than parameters.
StorageDuration getStorageDuration() const
Get the storage duration of this variable, per C++ [basic.stc].
bool isEscapingByref() const
Indicates the capture is a __block variable that is captured by a block that can potentially escape (...
mlir::ptr::MemorySpaceAttrInterface toCIRAddressSpaceAttr(mlir::MLIRContext &ctx, clang::LangAS langAS)
Convert an AST LangAS to the appropriate CIR address space attribute interface.
mlir::ptr::MemorySpaceAttrInterface normalizeDefaultAddressSpace(mlir::ptr::MemorySpaceAttrInterface addrSpace)
Normalize LangAddressSpace::Default to null (empty attribute).
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
@ EHCleanup
Denotes a cleanup that should run when a scope is exited using exceptional control flow (a throw stat...
@ 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
@ Address
A pointer to a ValueDecl.
Top level wrappers for InstallAPI frontend operations.
@ Ctor_Base
Base object ctor.
bool isa(CodeGen::Address addr)
@ SD_Automatic
Automatic storage duration (most local variables).
@ Dtor_Base
Base object dtor.
@ Dtor_Complete
Complete object dtor.
U cast(CodeGen::Address addr)
float __ovld __cnfn length(float)
Return the length of vector p, i.e., sqrt(p.x2 + p.y 2 + ...)
CallLifetimeEnd(mlir::Value addr)
bool isRedundantBeforeReturn() override
void emit(CIRGenFunction &cgf, Flags flags) override
Emit the cleanup.
static bool objCLifetime()
static bool addAutoInitAnnotation()
static bool addressSpace()
static bool emitNullabilityCheck()
static bool useEHCleanupForArray()
static bool vectorConstants()
static bool aggValueSlotMayOverlap()
static bool dtorCleanups()
static bool dataLayoutTypeAllocSize()
static bool opAllocaCaptureByInit()
static bool lifetimeMarkersBypass()
static bool opAllocaPreciseLifetime()
static bool cudaSupport()
static bool generateDebugInfo()
bool wasEmittedAsGlobal() const
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 useLifetimeMarkers
True if lifetime op should be used.
const clang::VarDecl * variable
bool isConstantAggregate
True if the variable is of aggregate type and has a constant initializer.
bool wasEmittedAsOffloadClause() const
Address getObjectAddress(CIRGenFunction &cgf) const
Returns the address of the object within this declaration.
A cleanup whose destructor call is not emitted where the cleanup is registered.
clang::CharUnits getPointerAlign() const
cir::PointerType allocaInt8PtrTy
void* in alloca address space
mlir::ptr::MemorySpaceAttrInterface getCIRAllocaAddressSpace() const