18#include "mlir/IR/Location.h"
20#include "clang/AST/Attrs.inc"
30#include "llvm/Support/SaveAndRestore.h"
38struct CallCleanupFunction final : EHScopeStack::Cleanup {
39 const CIRGenFunctionInfo &fnInfo;
43 SourceRange attrRange;
45 CallCleanupFunction(cir::FuncOp cleanupFn,
const CIRGenFunctionInfo *info,
46 Address addr, QualType varType,
const CleanupAttr *attr)
47 : fnInfo(*
info), addr(addr), varType(varType),
48 callee(CIRGenCallee::forDirect(
49 cleanupFn, CIRGenCalleeInfo(
attr->getFunctionDecl()))),
52 void emit(CIRGenFunction &cgf, Flags flags)
override {
53 assert(!fnInfo.arguments().empty());
54 QualType argTy = fnInfo.arguments()[0];
65 auto argPtrTy = mlir::cast<cir::PointerType>(cgf.
convertType(argTy));
72 cgf.
emitCall(fnInfo, callee, ReturnValueSlot(), args,
73 nullptr,
false, attrRange);
92 mlir::OpBuilder::InsertPoint ip) {
106 "emitAutoVarAlloca: decl escaping by reference");
130 getContext().getBaseElementType(ty)->isObjCObjectPointerType()) &&
144 (
cgm.getCodeGenOpts().MergeAllConstants && !nrvo &&
164 if (
const auto *cxxrd = dyn_cast<CXXRecordDecl>(rd);
165 (cxxrd && !cxxrd->hasTrivialDestructor()) ||
166 rd->isNonTrivialToPrimitiveDestroy()) {
171 cir::ConstantOp falseNVRO = builder.getFalse(loc);
175 assert(builder.getInsertionBlock());
176 builder.createStore(loc, falseNVRO, nrvoFlag);
188 nullptr,
nullptr, ip);
208 cgm.getDataLayout().getAlignment(defaultTy,
false));
211 mlir::Value v = builder.createStackSave(loc, defaultTy);
213 builder.createStore(loc, v, stack);
228 nullptr, builder.saveInsertionPoint());
236 emission.
addr = address;
256 if (constructor->isTrivial() && constructor->isDefaultConstructor() &&
257 !construct->requiresZeroInitialization())
266 mlir::TypedAttr constant) {
267 mlir::Type ty = constant.getType();
288 mlir::Location loc = builder.getUnknownLoc();
302 assert(emission.
variable &&
"emission was not valid!");
318 if (!init &&
type.isNonTrivialToPrimitiveDefaultInitialize() ==
321 "emitAutoVarInit: non-trivial to default initialize");
336 : (d.
getAttr<UninitializedAttr>()
340 auto initializeWhatIsTechnicallyUninitialized = [&](
Address addr) {
341 if (trivialAutoVarInit ==
349 initializeWhatIsTechnicallyUninitialized(addr);
353 mlir::Attribute constant;
362 if (constant && !mlir::isa<cir::ZeroAttr>(constant) &&
363 (trivialAutoVarInit !=
375 initializeWhatIsTechnicallyUninitialized(addr);
383 assert(addr.
isValid() &&
"Should have an address");
385 assert(allocaOp &&
"Address should come straight out of the alloca");
387 if (!allocaOp.use_empty())
395 auto typedConstant = mlir::dyn_cast<mlir::TypedAttr>(constant);
396 assert(typedConstant &&
"expected typed attribute");
400 assert(init &&
"expected initializer");
404 RValue::get(builder.getConstant(initLoc, typedConstant)), lv);
422 if (
const CleanupAttr *ca = d.
getAttr<CleanupAttr>()) {
425 cir::FuncOp f =
cgm.getAddrOfFunction(fd);
426 assert(f &&
"Could not find function!");
429 cgm.getTypes().arrangeFunctionDeclaration(fd);
449class LifetimeExtendedTemporaryFinder
456 explicit LifetimeExtendedTemporaryFinder(
const VarDecl &var) : var(var) {}
464 bool shouldVisitImplicitCode()
const {
return true; }
468 bool VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *m) {
474 SmallVector<const Expr *, 2> commaLHSs;
475 SmallVector<SubobjectAdjustment, 2> adjustments;
487 type->getBaseElementTypeUnsafe()->getAsCXXRecordDecl();
495SmallVector<QualType, 2>
500 LifetimeExtendedTemporaryFinder finder(d);
501 finder.TraverseStmt(
const_cast<Expr *
>(init));
523 "emitLoopConditionVariable: OpenCL local address space");
525 CIRGenFunction::VarDeclContext varDeclCtx{*
this, &d};
546 bool extendsTemporaries = !extendedTemporaries.empty();
551 if (
getLangOpts().Exceptions && extendsTemporaries &&
553 (extendedTemporaries.size() > 1 &&
556 "loop condition variable cleanup with a potentially-throwing "
557 "destructor before another destructor");
560 if (needsCleanup || extendsTemporaries) {
563 builder.getBoolTy(),
CharUnits::One(), loc,
"cond.cleanup.isactive",
566 builder.createFlagStore(loc,
false, activeFlag.
getPointer());
581 if (!extendsTemporaries &&
ehStack.stable_begin() != initDepth) {
583 "loop condition variable whose initializer leaves uncaptured "
588 for (
auto it =
ehStack.begin(), ie =
ehStack.find(initDepth); it != ie; ++it)
590 "loop condition variable initializer left an uncaptured cleanup");
596 builder.createFlagStore(loc,
true, activeFlag.
getPointer());
623 cir::GlobalLinkageKind linkage =
cgm.getCIRLinkageVarDefinition(&d);
637 CIRGenFunction::VarDeclContext varDeclCtx{*
this, &d};
647 std::string contextName;
649 if (
auto *cd = dyn_cast<CapturedDecl>(dc))
651 if (
const auto *fd = dyn_cast<FunctionDecl>(dc))
655 "getStaticDeclName: block decl context for static var");
658 "getStaticDeclName: ObjC decl context for static var");
661 "getStaticDeclName: Unknown context for static var decl");
671 cir::GlobalLinkageKind linkage) {
693 mlir::Attribute init =
nullptr;
695 d.
hasAttr<CUDASharedAttr>() || d.
hasAttr<LoaderUninitializedAttr>())
696 init = cir::UndefAttr::get(lty);
700 mlir::ptr::MemorySpaceAttrInterface addrSpace =
705 lty,
false, linkage, addrSpace);
709 gv.setInitialValueAttr(init);
710 gv.setAlignment(
getASTContext().getDeclAlign(&d).getAsAlign().value());
738 if (
const auto *cd = dyn_cast<CXXConstructorDecl>(dc))
740 else if (
const auto *dd = dyn_cast<CXXDestructorDecl>(dc))
742 else if (
const auto *fd = dyn_cast<FunctionDecl>(dc))
754 "OpenMP: DisableAutoDeclareTargetRAII for static local");
763 mlir::Attribute constAttr,
765 auto functionName = [&](
const DeclContext *dc) -> std::string {
766 if (
const auto *fd = dyn_cast<FunctionDecl>(dc)) {
767 if (
const auto *cc = dyn_cast<CXXConstructorDecl>(fd))
768 return cc->getNameAsString();
769 if (
const auto *cd = dyn_cast<CXXDestructorDecl>(fd))
770 return cd->getNameAsString();
772 }
else if (
const auto *om = dyn_cast<ObjCMethodDecl>(dc)) {
773 return om->getNameAsString();
779 llvm_unreachable(
"expected a function or method");
786 if (!cacheEntry || cacheEntry.getInitialValue() != constAttr) {
787 auto ty = mlir::cast<mlir::TypedAttr>(constAttr).getType();
788 bool isConstant =
true;
794 name = (
"__const." + functionName(dc) +
"." + d.
getName()).str();
796 llvm_unreachable(
"local variable has no parent function or method");
799 cir::GlobalOp gv = builder.createVersionedGlobal(
801 cir::GlobalLinkageKind::PrivateLinkage);
805 cir::GlobalLinkageKind::PrivateLinkage));
806 gv.setInitialValueAttr(constAttr);
807 gv.setAlignment(align.getAsAlign().value());
811 }
else if (cacheEntry.getAlignment() <
812 static_cast<uint64_t
>(align.getQuantity())) {
813 cacheEntry.setAlignment(align.getAsAlign().value());
818 mlir::Type eltTy = mlir::cast<mlir::TypedAttr>(constAttr).getType();
819 auto ptrTy = builder.getPointerTo(cacheEntry.getSymType());
820 mlir::Value globalPtr = cir::GetGlobalOp::create(
822 return Address(globalPtr, eltTy, align);
829 const VarDecl &d, cir::GlobalOp gv, cir::GetGlobalOp gvAddr) {
831 mlir::TypedAttr init = mlir::dyn_cast_if_present<mlir::TypedAttr>(
839 "constant l-value expression");
845 gv.setConstant(
false);
847 gvAddr.setStaticLocal(
true);
861 if (gv.getSymType() != init.getType()) {
862 gv.setSymType(init.getType());
870 gvAddr.getAddr().setType(builder.getPointerTo(init.getType()));
878 gv.setInitialValueAttr(init);
887 gvAddr.setStaticLocal(
true);
894 cir::GlobalLinkageKind linkage) {
898 cir::GlobalOp globalOp =
cgm.getOrCreateStaticVarDecl(d, linkage);
904 assert(getAddrOp &&
"expected cir::GetGlobalOp");
920 mlir::Type expectedType = addr.getType();
922 cir::GlobalOp var = globalOp;
928 if (d.
getInit() && !isCudaSharedVar)
931 var.setAlignment(alignment.
getAsAlign().value());
936 cgm.addGlobalAnnotations(&d, var);
937 if (d.
getAttr<PragmaClangBSSSectionAttr>())
939 "emitStaticVarDecl: CIR global BSS section attribute");
940 if (d.
getAttr<PragmaClangDataSectionAttr>())
942 "emitStaticVarDecl: CIR global Data section attribute");
943 if (d.
getAttr<PragmaClangRodataSectionAttr>())
945 "emitStaticVarDecl: CIR global Rodata section attribute");
946 if (d.
getAttr<PragmaClangRelroSectionAttr>())
948 "emitStaticVarDecl: CIR global Relro section attribute");
950 if (
const SectionAttr *sa = d.
getAttr<SectionAttr>())
951 var.setSectionAttr(builder.getStringAttr(sa->getName()));
953 if (
cgm.getCodeGenOpts().KeepPersistentStorageVariables)
962 mlir::Value castedAddr =
963 builder.createBitcast(getAddrOp.getAddr(), expectedType);
964 castedAddr =
cgm.castGlobalToDeclAddrSpace(castedAddr, d);
966 cgm.setStaticLocalDeclAddress(&d, var);
973 bool capturedByInit) {
978 if (capturedByInit) {
987 LValue lvalue,
bool capturedByInit) {
989 if (capturedByInit) {
996 if (
type->isReferenceType()) {
1011 "emitExprAsInit: complex type captured by init");
1026 llvm_unreachable(
"bad evaluation kind");
1031 case Decl::BuiltinTemplate:
1032 case Decl::TranslationUnit:
1033 case Decl::ExternCContext:
1034 case Decl::Namespace:
1035 case Decl::UnresolvedUsingTypename:
1036 case Decl::ClassTemplateSpecialization:
1037 case Decl::ClassTemplatePartialSpecialization:
1038 case Decl::VarTemplateSpecialization:
1039 case Decl::VarTemplatePartialSpecialization:
1040 case Decl::TemplateTypeParm:
1041 case Decl::UnresolvedUsingValue:
1042 case Decl::NonTypeTemplateParm:
1043 case Decl::CXXDeductionGuide:
1044 case Decl::CXXMethod:
1045 case Decl::CXXConstructor:
1046 case Decl::CXXDestructor:
1047 case Decl::CXXConversion:
1049 case Decl::MSProperty:
1050 case Decl::IndirectField:
1051 case Decl::ObjCIvar:
1052 case Decl::ObjCAtDefsField:
1054 case Decl::ImplicitParam:
1055 case Decl::ClassTemplate:
1056 case Decl::VarTemplate:
1057 case Decl::FunctionTemplate:
1058 case Decl::TypeAliasTemplate:
1059 case Decl::TemplateTemplateParm:
1060 case Decl::ObjCMethod:
1061 case Decl::ObjCCategory:
1062 case Decl::ObjCProtocol:
1063 case Decl::ObjCInterface:
1064 case Decl::ObjCCategoryImpl:
1065 case Decl::ObjCImplementation:
1066 case Decl::ObjCProperty:
1067 case Decl::ObjCCompatibleAlias:
1068 case Decl::PragmaComment:
1069 case Decl::PragmaDetectMismatch:
1070 case Decl::AccessSpec:
1071 case Decl::LinkageSpec:
1073 case Decl::ObjCPropertyImpl:
1074 case Decl::FileScopeAsm:
1076 case Decl::FriendTemplate:
1078 case Decl::OutlinedFunction:
1079 case Decl::Captured:
1080 case Decl::UsingShadow:
1081 case Decl::ConstructorUsingShadow:
1082 case Decl::ObjCTypeParam:
1084 case Decl::UnresolvedUsingIfExists:
1085 case Decl::HLSLBuffer:
1086 case Decl::HLSLRootSignature:
1087 llvm_unreachable(
"Declaration should not be in declstmts!");
1089 case Decl::Function:
1090 case Decl::EnumConstant:
1091 case Decl::ExplicitInstantiation:
1092 case Decl::StaticAssert:
1096 case Decl::TemplateParamObject:
1099 case Decl::LifetimeExtendedTemporary:
1100 case Decl::RequiresExprBody:
1101 case Decl::UnnamedGlobalConstant:
1107 case Decl::CXXRecord:
1108 case Decl::NamespaceAlias:
1110 case Decl::UsingEnum:
1111 case Decl::UsingDirective:
1115 case Decl::Decomposition: {
1118 "Should not see file-scope variables inside a function!");
1120 if (evaluateConditionDecl)
1124 case Decl::OpenACCDeclare:
1127 case Decl::OpenACCRoutine:
1130 case Decl::OMPThreadPrivate:
1133 case Decl::OMPGroupPrivate:
1136 case Decl::OMPAllocate:
1139 case Decl::OMPCapturedExpr:
1142 case Decl::OMPRequires:
1145 case Decl::OMPDeclareMapper:
1148 case Decl::OMPDeclareReduction:
1152 case Decl::TypeAlias: {
1159 case Decl::ImplicitConceptSpecialization:
1160 case Decl::TopLevelStmt:
1161 case Decl::UsingPack:
1162 case Decl::CXXExpansionStmt:
1164 std::string(
"emitDecl: unhandled decl type: ") +
1171 if (!
sanOpts.has(SanitizerKind::NullabilityAssign))
1181 : addr(addr),
type(
type), destroyer(destroyer) {
1196 DestroyNRVOVariable(Address addr, QualType
type, mlir::Value nrvoFlag)
1197 : nrvoFlag(nrvoFlag), addr(addr), ty(
type) {}
1199 mlir::Value nrvoFlag;
1203 void emit(CIRGenFunction &cgf, Flags flags)
override {
1205 bool nrvo = flags.isForNormalCleanup() && nrvoFlag;
1208 mlir::OpBuilder::InsertionGuard guard(builder);
1211 mlir::Location loc = addr.
getPointer().getLoc();
1213 mlir::Value notNRVO = builder.
createNot(didNRVO);
1214 cir::IfOp::create(builder, loc, notNRVO,
false,
1215 [&](mlir::OpBuilder &b, mlir::Location) {
1216 static_cast<Derived *
>(
this)->emitDestructorCall(cgf);
1220 static_cast<Derived *
>(
this)->emitDestructorCall(cgf);
1224 virtual ~DestroyNRVOVariable() =
default;
1227struct DestroyNRVOVariableCXX final
1228 : DestroyNRVOVariable<DestroyNRVOVariableCXX> {
1229 DestroyNRVOVariableCXX(Address addr, QualType
type,
1230 const CXXDestructorDecl *dtor, mlir::Value nrvoFlag)
1231 : DestroyNRVOVariable<DestroyNRVOVariableCXX>(addr,
type, nrvoFlag),
1234 const CXXDestructorDecl *dtor;
1236 void emitDestructorCall(CIRGenFunction &cgf) {
1245 CallStackRestore(Address stack) : stack(stack) {}
1247 void emit(CIRGenFunction &cgf, Flags flags)
override {
1248 mlir::Location loc = stack.getPointer().getLoc();
1257 mlir::Value arrayBegin;
1259 QualType elementType;
1260 CharUnits elementAlign;
1263 IrregularPartialArrayDestroy(mlir::Value arrayBegin, Address arrayEndPointer,
1264 QualType elementType, CharUnits elementAlign,
1266 : arrayBegin(arrayBegin), arrayEndPointer(arrayEndPointer),
1267 elementType(elementType), elementAlign(elementAlign),
1268 destroyer(destroyer) {}
1270 void emit(CIRGenFunction &cgf, Flags flags)
override {
1272 mlir::Location loc = arrayBegin.getLoc();
1274 mlir::Value arrayEnd = builder.
createLoad(loc, arrayEndPointer);
1283 mlir::cast<cir::PointerType>(arrayBegin.getType()).getAddrSpace());
1285 mlir::Value begin = arrayBegin;
1286 if (baseElementType != elementType) {
1295 cir::CmpOp::create(builder, loc, cir::CmpOpKind::ne, arrayEnd, begin);
1297 builder, loc, ne,
false,
1298 [&](mlir::OpBuilder &b, mlir::Location loc) {
1305 [&](mlir::OpBuilder &b, mlir::Location loc) {
1306 mlir::Value cur = builder.
createLoad(loc, iterAddr);
1307 mlir::Value cmp = cir::CmpOp::create(
1308 builder, loc, cir::CmpOpKind::ne, cur, begin);
1312 [&](mlir::OpBuilder &b, mlir::Location loc) {
1313 mlir::Value cur = builder.
createLoad(loc, iterAddr);
1315 loc, mlir::cast<cir::IntType>(cgf.
ptrDiffTy), -1);
1316 mlir::Value prev = cir::PtrStrideOp::create(
1317 builder, loc, ptrToElmType, cur, negOne);
1320 destroyer(cgf, elemAddr, baseElementType);
1341 EHCleanup, arrayBegin, arrayEndPointer, elementType, elementAlign,
1360 assert(dtorKind &&
"cannot push destructor for trivial type");
1373 assert(dtorKind &&
"cannot push destructor for trivial type");
1382 bool useEHCleanupForArray) {
1390 bool useEHCleanupForArray,
const ValueDecl *extendingDecl) {
1392 cgm.errorNYI(
"conditional lifetime-extended destroy");
1399 useEHCleanupForArray);
1417 std::optional<CapturedCleanups::CaptureScope> capture;
1438 mlir::Value numElements,
1447 cir::PointerType ptrToElmType = builder.getPointerTo(
1449 mlir::cast<cir::PointerType>(begin.getType()).getAddrSpace());
1451 auto regionBuilder = [&](mlir::OpBuilder &b, mlir::Location loc) {
1452 mlir::BlockArgument arg =
1453 b.getInsertionBlock()->addArgument(ptrToElmType, loc);
1458 destroyer(*
this, curAddr, elementType);
1460 cir::YieldOp::create(b, loc);
1464 if (
auto constantCount = numElements.getDefiningOp<cir::ConstantOp>()) {
1466 if (
auto constIntAttr = constantCount.getValueAttr<cir::IntAttr>())
1467 size = constIntAttr.getUInt();
1468 auto arrayTy = cir::ArrayType::get(cirElementType, size);
1469 mlir::Value arrayOp = builder.createPtrBitcast(begin, arrayTy);
1476 mlir::Value elemBegin = builder.createPtrBitcast(begin, cirElementType);
1477 cir::ArrayDtor::create(builder,
getLoc(*
currSrcLoc), elemBegin, numElements,
1492 return destroyer(*
this, addr,
type);
1500 auto constantCount =
length.getDefiningOp<cir::ConstantOp>();
1501 if (constantCount) {
1502 auto constIntAttr = mlir::dyn_cast<cir::IntAttr>(constantCount.getValue());
1503 if (constIntAttr && constIntAttr.getUInt() == 0)
1512 if (constantCount && constantCount.use_empty())
1513 constantCount.erase();
1520 llvm_unreachable(
"no destroyer for trivial dtor");
1526 cgm.errorNYI(
"getDestroyer: other destruction kind");
1529 llvm_unreachable(
"Unknown DestructionKind");
1533 ehStack.pushCleanup<CallStackRestore>(
kind, spMem);
1554 llvm_unreachable(
"no cleanup for trivially-destructible variable");
1560 assert(!
type->isArrayType());
1562 ehStack.pushCleanup<DestroyNRVOVariableCXX>(cleanupKind, addr,
type, dtor,
1572 cgm.errorNYI(var->getSourceRange(),
1573 "emitAutoVarTypeCleanup: other dtor kind");
1582 ehStack.pushCleanup<DestroyObject>(cleanupKind, addr,
type, destroyer);
1586 if (
auto *dd = dyn_cast_if_present<DecompositionDecl>(vd)) {
1587 for (
auto *b : dd->flat_bindings())
1588 if (
auto *hd = b->getHoldingVar())
1594 if (!shouldEmitLifetimeMarkers)
1597 assert(mlir::cast<cir::PointerType>(addr.getType()).getAddrSpace() ==
1599 "Pointer should be in alloca address space");
1601 cir::LifetimeStartOp::create(builder, loc, addr);
1606 if (!shouldEmitLifetimeMarkers)
1609 assert(mlir::cast<cir::PointerType>(addr.getType()).getAddrSpace() ==
1611 "Pointer should be in alloca address space");
1613 cir::LifetimeEndOp::create(builder, loc, addr);
static bool emit(llvm::SmallVectorImpl< std::byte > &Code, const T &Val)
Helper to write bytecode and bail out if 32-bit offsets become invalid.
static bool isRedundantBeforeReturn(mlir::Region &cleanupRegion)
static bool destructorMayThrow(QualType type)
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
static CharSourceRange getRange(const CharSourceRange &EditRange, const SourceManager &SM, const LangOptions &LangOpts, bool IncludeMacroExpansion)
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...
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
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.
mlir::Operation * getDefiningOp() const
Get the operation which defines this address.
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 variables whose lifetime ends in a region owned by an enclosing op rather than ...
void emitOpenACCRoutine(const OpenACCRoutineDecl &d)
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.
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.
llvm::SmallVector< PendingCleanupEntry > lifetimeExtendedCleanupStack
ConditionalEvaluation * hiddenOutermostConditional
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 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.
void emitLoopConditionVariable(const clang::VarDecl &d, CapturedCleanups &condCleanup, llvm::ArrayRef< QualType > extendedTemporaries)
Emit a loop's condition-variable declaration.
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...
mlir::Value performAddrSpaceCast(mlir::Value v, mlir::Type destTy) const
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)
const LifetimeExtensionCapture * lifetimeExtensionCapture
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...
void pushLifetimeExtendedDestroy(CleanupKind kind, Address addr, QualType type, Destroyer *destroyer, bool useEHCleanupForArray, const clang::ValueDecl *extendingDecl)
void popCleanupBlocks(EHScopeStack::stable_iterator oldCleanupStackDepth, ArrayRef< mlir::Value * > valuesToReload={})
Takes the old cleanup stack size and emits the cleanup blocks that have been added.
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)
RValue emitCall(const CIRGenFunctionInfo &funcInfo, const CIRGenCallee &callee, ReturnValueSlot returnValue, const CallArgList &args, cir::CIRCallOpInterface *callOp, bool isMustTail, SourceRange clangLoc)
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 ...
static llvm::SmallVector< QualType, 2 > getLifetimeExtendedTemporariesWithDestructor(const clang::VarDecl &d)
The types of the temporaries with a destructor that the initializer of the variable d,...
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)
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)
mlir::TypedAttr emitNullConstantAttr(QualType t)
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)
mlir::ptr::MemorySpaceAttrInterface getGlobalCIRAddressSpace(LangAS as)
Return the CIR address space attribute for a global in as, honoring the target address space map wher...
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 add(RValue rvalue, clang::QualType 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.
A saved depth on the scope stack.
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.
Represents a C++ struct/union/class.
bool hasTrivialDestructor() const
Determine whether this class has a trivial destructor (C++ [class.dtor]p3)
CXXDestructorDecl * getDestructor() const
Returns the destructor decl for this class.
This is an opaque type for sizes expressed in character units.
llvm::Align getAsAlign() const
Returns Quantity as a valid llvm::Align, Beware llvm::Align assumes power of two 8-bit bytes.
static CharUnits 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)
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.
const Expr * skipRValueSubobjectAdjustments(SmallVectorImpl< const Expr * > &CommaLHS, SmallVectorImpl< SubobjectAdjustment > &Adjustments) const
Walk outwards from an expression we want to bind a reference to and find the expression whose lifetim...
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...
Represents a function declaration or definition.
Represents a prototype with parameter type info, e.g.
GlobalDecl - represents a global declaration.
const Decl * getDecl() const
StorageDuration getStorageDuration() const
Retrieve the storage duration for the materialized temporary.
Expr * getSubExpr() const
Retrieve the temporary-generating subexpression whose value will be materialized into a glvalue.
ValueDecl * getExtendingDecl()
Get the declaration which triggered the lifetime-extension of this temporary, if any.
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.
DestructionKind isDestructedType() const
Returns a nonzero value if objects of this type require non-trivial work to clean up after.
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.
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
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....
const T * castAs() const
Member-template castAs<specific type>.
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 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< Attr > attr
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const AstTypeMatcher< ArrayType > arrayType
@ Address
A pointer to a ValueDecl.
void info(bool Verbose, unsigned Level, const char *Fmt, Ts &&...Args)
Prints an indented note to stderr when Verbose is set.
Top level wrappers for InstallAPI frontend operations.
@ Ctor_Base
Base object ctor.
bool isa(CodeGen::Address addr)
bool isUnresolvedExceptionSpec(ExceptionSpecificationType ESpecType)
@ SD_Automatic
Automatic storage duration (most local variables).
@ Dtor_Base
Base object dtor.
@ Dtor_Complete
Complete object dtor.
U cast(CodeGen::Address addr)
__DEVICE__ _Tp arg(const std::complex< _Tp > &__c)
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 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.
Set by emitLoopConditionVariable while it emits the initializer of a loop condition variable that lif...
A cleanup whose destructor call is not emitted where the cleanup is registered.
CapturedCleanups * capturedBy
If set, the cleanup is captured by this owner instead of opening a cir.cleanup.scope when it is pushe...
clang::CharUnits getPointerAlign() const
cir::PointerType allocaInt8PtrTy
void* in alloca address space
mlir::ptr::MemorySpaceAttrInterface getCIRAllocaAddressSpace() const