16#include "mlir/IR/Builders.h"
17#include "mlir/IR/Location.h"
18#include "mlir/Support/LLVM.h"
26#include "llvm/Support/SaveAndRestore.h"
36 const AtomicAttr *aa) {
39 for (
auto option : aa->atomicOptions()) {
41 case AtomicAttr::remote_memory:
44 case AtomicAttr::no_remote_memory:
47 case AtomicAttr::fine_grained_memory:
50 case AtomicAttr::no_fine_grained_memory:
53 case AtomicAttr::ignore_denormal_mode:
56 case AtomicAttr::no_ignore_denormal_mode:
65 const Stmt *exprResult,
74 if (
const auto *ls = dyn_cast<LabelStmt>(exprResult)) {
75 if (cgf.
emitLabel(*ls->getDecl()).failed())
76 return mlir::failure();
77 exprResult = ls->getSubStmt();
78 }
else if (
const auto *as = dyn_cast<AttributedStmt>(exprResult)) {
81 exprResult = as->getSubStmt();
83 llvm_unreachable(
"Unknown value statement");
99 return mlir::success();
104 mlir::LogicalResult result = mlir::success();
106 assert((!lastValue || (lastValue && exprResult)) &&
107 "If lastValue is not null then the CompoundStmt must have a "
110 for (
const Stmt *curStmt : s.
body()) {
111 const bool saveResult = lastValue && exprResult == curStmt;
114 result = mlir::failure();
116 if (
emitStmt(curStmt,
false).failed())
117 result = mlir::failure();
129 const AtomicAttr *atomicAttr =
nullptr;
132 switch (
attr->getKind()) {
139 case attr::NoConvergent:
140 case attr::AMDGPUAvailableVisible:
141 case attr::HLSLControlFlowHint:
143 "Unimplemented statement attribute: ",
attr->getKind());
147 alwaysinline =
false;
149 case attr::AlwaysInline:
153 case attr::MustTail: {
159 case attr::CXXAssume: {
161 if (
getLangOpts().CXXAssumptions && builder.getInsertionBlock() &&
165 assumptionValue, cir::AssumeBundleKind::None,
172 assert(!(alwaysinline && noinline) &&
173 "alwaysinline and noinline are mutually exclusive");
185 mlir::LogicalResult result =
188 cgm.setAtomicOpts(savedAtomicOpts);
198 mlir::OpBuilder::InsertPoint scopeInsPt;
199 cir::ScopeOp::create(
201 [&](mlir::OpBuilder &b, mlir::Type &
type, mlir::Location loc) {
202 scopeInsPt = b.saveInsertionPoint();
204 mlir::OpBuilder::InsertionGuard guard(builder);
205 builder.restoreInsertionPoint(scopeInsPt);
206 LexicalScope lexScope(*
this, scopeLoc, builder.getInsertionBlock());
217 bool useCurrentScope,
220 return mlir::success();
224 case Stmt::CXXCatchStmtClass:
225 case Stmt::SEHExceptStmtClass:
226 case Stmt::SEHFinallyStmtClass:
227 case Stmt::MSDependentExistsStmtClass:
228 case Stmt::UnresolvedSYCLKernelCallStmtClass:
229 llvm_unreachable(
"invalid statement class to emit generically");
230 case Stmt::BreakStmtClass:
231 case Stmt::NullStmtClass:
232 case Stmt::CompoundStmtClass:
233 case Stmt::ContinueStmtClass:
234 case Stmt::DeclStmtClass:
235 case Stmt::ReturnStmtClass:
236 llvm_unreachable(
"should have emitted these statements as simple");
238#define STMT(Type, Base)
239#define ABSTRACT_STMT(Op)
240#define EXPR(Type, Base) case Stmt::Type##Class:
241#include "clang/AST/StmtNodes.inc"
243 assert(builder.getInsertionBlock() &&
244 "expression emission must have an insertion point");
252 return mlir::success();
254 case Stmt::IfStmtClass:
256 case Stmt::SwitchStmtClass:
258 case Stmt::ForStmtClass:
260 case Stmt::WhileStmtClass:
262 case Stmt::DoStmtClass:
264 case Stmt::CXXTryStmtClass:
266 case Stmt::CXXForRangeStmtClass:
268 case Stmt::CoroutineBodyStmtClass:
270 case Stmt::IndirectGotoStmtClass:
272 case Stmt::CoreturnStmtClass:
274 case Stmt::SYCLKernelCallStmtClass:
276 case Stmt::OpenACCComputeConstructClass:
278 case Stmt::OpenACCLoopConstructClass:
280 case Stmt::OpenACCCombinedConstructClass:
282 case Stmt::OpenACCDataConstructClass:
284 case Stmt::OpenACCEnterDataConstructClass:
286 case Stmt::OpenACCExitDataConstructClass:
288 case Stmt::OpenACCHostDataConstructClass:
290 case Stmt::OpenACCWaitConstructClass:
292 case Stmt::OpenACCInitConstructClass:
294 case Stmt::OpenACCShutdownConstructClass:
296 case Stmt::OpenACCSetConstructClass:
298 case Stmt::OpenACCUpdateConstructClass:
300 case Stmt::OpenACCCacheConstructClass:
302 case Stmt::OpenACCAtomicConstructClass:
304 case Stmt::GCCAsmStmtClass:
305 case Stmt::MSAsmStmtClass:
307 case Stmt::OMPScopeDirectiveClass:
309 case Stmt::OMPErrorDirectiveClass:
311 case Stmt::OMPParallelDirectiveClass:
313 case Stmt::OMPTaskwaitDirectiveClass:
315 case Stmt::OMPTaskyieldDirectiveClass:
317 case Stmt::OMPBarrierDirectiveClass:
319 case Stmt::OMPMetaDirectiveClass:
321 case Stmt::OMPCanonicalLoopClass:
323 case Stmt::OMPSimdDirectiveClass:
325 case Stmt::OMPTileDirectiveClass:
327 case Stmt::OMPUnrollDirectiveClass:
329 case Stmt::OMPFuseDirectiveClass:
331 case Stmt::OMPForDirectiveClass:
333 case Stmt::OMPForSimdDirectiveClass:
335 case Stmt::OMPSectionsDirectiveClass:
337 case Stmt::OMPSectionDirectiveClass:
339 case Stmt::OMPSingleDirectiveClass:
341 case Stmt::OMPMasterDirectiveClass:
343 case Stmt::OMPCriticalDirectiveClass:
345 case Stmt::OMPParallelForDirectiveClass:
347 case Stmt::OMPParallelForSimdDirectiveClass:
350 case Stmt::OMPParallelMasterDirectiveClass:
352 case Stmt::OMPParallelSectionsDirectiveClass:
355 case Stmt::OMPTaskDirectiveClass:
357 case Stmt::OMPTaskgroupDirectiveClass:
359 case Stmt::OMPFlushDirectiveClass:
361 case Stmt::OMPDepobjDirectiveClass:
363 case Stmt::OMPScanDirectiveClass:
365 case Stmt::OMPOrderedStandaloneDirectiveClass:
368 case Stmt::OMPOrderedBlockAssocDirectiveClass:
371 case Stmt::OMPAtomicDirectiveClass:
373 case Stmt::OMPTargetDirectiveClass:
375 case Stmt::OMPTeamsDirectiveClass:
377 case Stmt::OMPCancellationPointDirectiveClass:
380 case Stmt::OMPCancelDirectiveClass:
382 case Stmt::OMPTargetDataDirectiveClass:
384 case Stmt::OMPTargetEnterDataDirectiveClass:
387 case Stmt::OMPTargetExitDataDirectiveClass:
389 case Stmt::OMPTargetParallelDirectiveClass:
391 case Stmt::OMPTargetParallelForDirectiveClass:
394 case Stmt::OMPTaskLoopDirectiveClass:
396 case Stmt::OMPTaskLoopSimdDirectiveClass:
398 case Stmt::OMPMaskedTaskLoopDirectiveClass:
400 case Stmt::OMPMaskedTaskLoopSimdDirectiveClass:
403 case Stmt::OMPMasterTaskLoopDirectiveClass:
405 case Stmt::OMPMasterTaskLoopSimdDirectiveClass:
408 case Stmt::OMPParallelGenericLoopDirectiveClass:
411 case Stmt::OMPParallelMaskedDirectiveClass:
413 case Stmt::OMPParallelMaskedTaskLoopDirectiveClass:
416 case Stmt::OMPParallelMaskedTaskLoopSimdDirectiveClass:
419 case Stmt::OMPParallelMasterTaskLoopDirectiveClass:
422 case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass:
425 case Stmt::OMPDistributeDirectiveClass:
427 case Stmt::OMPDistributeParallelForDirectiveClass:
430 case Stmt::OMPDistributeParallelForSimdDirectiveClass:
433 case Stmt::OMPDistributeSimdDirectiveClass:
435 case Stmt::OMPTargetParallelGenericLoopDirectiveClass:
438 case Stmt::OMPTargetParallelForSimdDirectiveClass:
441 case Stmt::OMPTargetSimdDirectiveClass:
443 case Stmt::OMPTargetTeamsGenericLoopDirectiveClass:
446 case Stmt::OMPTargetUpdateDirectiveClass:
448 case Stmt::OMPTeamsDistributeDirectiveClass:
451 case Stmt::OMPTeamsDistributeSimdDirectiveClass:
454 case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
457 case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
460 case Stmt::OMPTeamsGenericLoopDirectiveClass:
463 case Stmt::OMPTargetTeamsDirectiveClass:
465 case Stmt::OMPTargetTeamsDistributeDirectiveClass:
468 case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
471 case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
474 case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
477 case Stmt::OMPInteropDirectiveClass:
479 case Stmt::OMPDispatchDirectiveClass:
481 case Stmt::OMPGenericLoopDirectiveClass:
483 case Stmt::OMPReverseDirectiveClass:
485 case Stmt::OMPSplitDirectiveClass:
487 case Stmt::OMPInterchangeDirectiveClass:
489 case Stmt::OMPFlattenDirectiveClass:
491 case Stmt::OMPAssumeDirectiveClass:
493 case Stmt::OMPMaskedDirectiveClass:
495 case Stmt::OMPStripeDirectiveClass:
497 case Stmt::LabelStmtClass:
498 case Stmt::AttributedStmtClass:
499 case Stmt::GotoStmtClass:
500 case Stmt::DefaultStmtClass:
501 case Stmt::CaseStmtClass:
502 case Stmt::SEHLeaveStmtClass:
503 case Stmt::ObjCAtTryStmtClass:
504 case Stmt::ObjCAtThrowStmtClass:
505 case Stmt::ObjCAtSynchronizedStmtClass:
506 case Stmt::ObjCForCollectionStmtClass:
507 case Stmt::ObjCAutoreleasePoolStmtClass:
508 case Stmt::SEHTryStmtClass:
509 case Stmt::ObjCAtCatchStmtClass:
510 case Stmt::ObjCAtFinallyStmtClass:
511 case Stmt::DeferStmtClass:
512 case Stmt::CXXExpansionStmtPatternClass:
513 case Stmt::CXXExpansionStmtInstantiationClass:
516 return mlir::failure();
517 case Stmt::CapturedStmtClass:
518 llvm_unreachable(
"CapturedStmt must be handled by the parent directive");
521 llvm_unreachable(
"Unexpected statement class");
525 bool useCurrentScope) {
528 return mlir::failure();
529 case Stmt::DeclStmtClass:
531 case Stmt::CompoundStmtClass:
535 case Stmt::GotoStmtClass:
537 case Stmt::ContinueStmtClass:
541 case Stmt::NullStmtClass:
544 case Stmt::LabelStmtClass:
546 case Stmt::CaseStmtClass:
547 case Stmt::DefaultStmtClass:
553 case Stmt::BreakStmtClass:
555 case Stmt::ReturnStmtClass:
557 case Stmt::AttributedStmtClass:
561 return mlir::success();
567 return mlir::failure();
577 mlir::Location loc) {
582 unsigned numBlocks = r.getBlocks().size();
583 for (
auto &block : r.getBlocks()) {
586 if (numBlocks != 1 && block.empty() && block.hasNoPredecessors() &&
587 block.hasNoSuccessors())
588 eraseBlocks.push_back(&block);
591 !block.back().hasTrait<mlir::OpTrait::IsTerminator>()) {
592 mlir::OpBuilder::InsertionGuard guardCase(builder);
593 builder.setInsertionPointToEnd(&block);
594 builder.createYield(loc);
598 for (
auto *b : eraseBlocks)
603 mlir::LogicalResult res = mlir::success();
606 const Stmt *constevalExecuted;
609 if (!constevalExecuted) {
617 auto ifStmtBuilder = [&]() -> mlir::LogicalResult {
619 return emitStmt(constevalExecuted,
true);
623 return mlir::failure();
636 std::swap(executed, skipped);
645 return mlir::success();
658 cir::ScopeOp::create(builder, scopeLoc,
659 [&](mlir::OpBuilder &b, mlir::Location loc) {
661 builder.getInsertionBlock()};
662 res = ifStmtBuilder();
669 assert(builder.getInsertionBlock() &&
"expected valid insertion point");
674 return mlir::success();
682 bool createNewScope =
false;
683 if (
const auto *ewc = dyn_cast_or_null<ExprWithCleanups>(rv)) {
684 rv = ewc->getSubExpr();
685 createNewScope =
true;
688 auto handleReturnVal = [&]() {
699 builder.createFlagStore(loc,
true, nrvoFlag);
710 ->isReferenceType()) {
714 builder.CIRBaseBuilderTy::createStore(loc, result.
getValue(),
717 mlir::Value value =
nullptr;
722 builder.CIRBaseBuilderTy::createStore(loc, value, *
fnRetAlloca);
741 if (!createNewScope) {
757 cir::AllocaOp retAlloca =
758 mlir::cast<cir::AllocaOp>(
fnRetAlloca->getDefiningOp());
759 auto value = cir::LoadOp::create(builder, loc, retAlloca.getAllocaType(),
762 cir::ReturnOp::create(builder, loc, {value});
764 cir::ReturnOp::create(builder, loc);
770 builder.createBlock(builder.getBlock()->getParent());
771 return mlir::success();
787 builder.createBlock(builder.getBlock()->getParent());
789 return mlir::success();
798 return mlir::success();
808 builder.createBlock(builder.getBlock()->getParent());
809 return mlir::success();
817 builder.createBlock(builder.getBlock()->getParent());
819 return mlir::success();
826 mlir::Block *currBlock = builder.getBlock();
827 mlir::Block *labelBlock = currBlock;
829 if (!currBlock->empty() || currBlock->isEntryBlock()) {
831 mlir::OpBuilder::InsertionGuard guard(builder);
832 labelBlock = builder.createBlock(builder.getBlock()->getParent());
837 builder.setInsertionPointToEnd(labelBlock);
846 return mlir::success();
853 builder.createBlock(builder.getBlock()->getParent());
855 return mlir::success();
861 mlir::ArrayAttr value, CaseOpKind
kind,
862 bool buildingTopLevelCase) {
865 "only case or default stmt go here");
867 mlir::LogicalResult result = mlir::success();
869 mlir::Location loc =
getLoc(
stmt->getBeginLoc());
872 SubStmtKind subStmtKind = SubStmtKind::Other;
873 const Stmt *sub =
stmt->getSubStmt();
875 mlir::OpBuilder::InsertPoint insertPoint;
876 CaseOp::create(builder, loc, value,
kind, insertPoint);
879 mlir::OpBuilder::InsertionGuard guardSwitch(builder);
880 builder.restoreInsertionPoint(insertPoint);
883 subStmtKind = SubStmtKind::Default;
884 builder.createYield(loc);
886 subStmtKind = SubStmtKind::Case;
887 builder.createYield(loc);
892 insertPoint = builder.saveInsertionPoint();
927 if (subStmtKind == SubStmtKind::Case) {
929 }
else if (subStmtKind == SubStmtKind::Default) {
931 buildingTopLevelCase);
932 }
else if (buildingTopLevelCase) {
936 builder.restoreInsertionPoint(insertPoint);
944 bool buildingTopLevelCase) {
945 cir::CaseOpKind
kind;
946 mlir::ArrayAttr value;
952 condType = builder.getUIntNTy(1);
958 llvm::APSInt endVal = rhs->EvaluateKnownConstInt(
getContext());
959 value = builder.getArrayAttr({cir::IntAttr::get(condType, intVal),
960 cir::IntAttr::get(condType, endVal)});
961 kind = cir::CaseOpKind::Range;
963 value = builder.getArrayAttr({cir::IntAttr::get(condType, intVal)});
964 kind = cir::CaseOpKind::Equal;
968 buildingTopLevelCase);
973 bool buildingTopLevelCase) {
975 cir::CaseOpKind::Default, buildingTopLevelCase);
979 bool buildingTopLevelCase) {
981 "build switch case without specifying the type of the condition");
985 buildingTopLevelCase);
989 buildingTopLevelCase);
991 llvm_unreachable(
"expect case or default stmt");
1000 auto forStmtBuilder = [&]() -> mlir::LogicalResult {
1001 mlir::LogicalResult loopRes = mlir::success();
1005 return mlir::failure();
1007 return mlir::failure();
1009 return mlir::failure();
1011 return mlir::failure();
1015 forOp = builder.createFor(
1018 [&](mlir::OpBuilder &b, mlir::Location loc) {
1019 assert(!cir::MissingFeatures::createProfileWeightsForLoop());
1020 assert(!cir::MissingFeatures::emitCondLikelihoodViaExpectIntrinsic());
1021 mlir::Value condVal = evaluateExprAsBool(s.getCond());
1022 builder.createCondition(condVal);
1025 [&](mlir::OpBuilder &b, mlir::Location loc) {
1029 RunCleanupsScope bodyScope(*this);
1030 bool useCurrentScope = true;
1031 if (emitStmt(s.getLoopVarStmt(), useCurrentScope).failed())
1032 loopRes = mlir::failure();
1033 if (emitStmt(s.getBody(), useCurrentScope).failed())
1034 loopRes = mlir::failure();
1038 [&](mlir::OpBuilder &b, mlir::Location loc) {
1040 if (emitStmt(s.getInc(), true).failed())
1041 loopRes = mlir::failure();
1042 builder.createYield(loc);
1047 mlir::LogicalResult res = mlir::success();
1049 cir::ScopeOp::create(builder, scopeLoc,
1050 [&](mlir::OpBuilder &b, mlir::Location loc) {
1056 builder.getInsertionBlock()};
1057 res = forStmtBuilder();
1064 return mlir::success();
1071 auto forStmtBuilder = [&]() -> mlir::LogicalResult {
1072 mlir::LogicalResult loopRes = mlir::success();
1076 return mlir::failure();
1088 condVarExtendedTemporaries =
1090 bool needsCondCleanup =
1093 shouldEmitLifetimeMarkersForAutoVar() ||
1094 !condVarExtendedTemporaries.empty());
1097 auto condBuilder = [&](mlir::OpBuilder &b, mlir::Location loc) {
1100 mlir::Value condVal;
1105 condVarExtendedTemporaries);
1111 condVal = cir::ConstantOp::create(b, loc, builder.getTrueAttr());
1113 builder.createCondition(condVal);
1115 auto bodyBuilder = [&](mlir::OpBuilder &b, mlir::Location loc) {
1120 loopRes = mlir::failure();
1123 auto stepBuilder = [&](mlir::OpBuilder &b, mlir::Location loc) {
1126 loopRes = mlir::failure();
1127 builder.createYield(loc);
1130 if (needsCondCleanup) {
1131 cir::CleanupKind cleanupKind =
getLangOpts().Exceptions
1132 ? cir::CleanupKind::All
1133 : cir::CleanupKind::Normal;
1134 forOp = builder.createFor(
1137 [&](mlir::OpBuilder &b, mlir::Location loc) {
1138 loopCondScope.emitIntoCleanupRegion(loc);
1139 builder.createYield(loc);
1144 bodyBuilder, stepBuilder);
1149 auto res = mlir::success();
1151 cir::ScopeOp::create(builder, scopeLoc,
1152 [&](mlir::OpBuilder &b, mlir::Location loc) {
1154 builder.getInsertionBlock()};
1155 res = forStmtBuilder();
1162 return mlir::success();
1166 cir::DoWhileOp doWhileOp;
1169 auto doStmtBuilder = [&]() -> mlir::LogicalResult {
1170 mlir::LogicalResult loopRes = mlir::success();
1174 doWhileOp = builder.createDoWhile(
1177 [&](mlir::OpBuilder &b, mlir::Location loc) {
1178 assert(!cir::MissingFeatures::createProfileWeightsForLoop());
1179 assert(!cir::MissingFeatures::emitCondLikelihoodViaExpectIntrinsic());
1183 mlir::Value condVal = evaluateExprAsBool(s.getCond());
1184 builder.createCondition(condVal);
1187 [&](mlir::OpBuilder &b, mlir::Location loc) {
1189 RunCleanupsScope bodyScope(*this);
1190 if (emitStmt(s.getBody(), false).failed())
1191 loopRes = mlir::failure();
1197 mlir::LogicalResult res = mlir::success();
1199 cir::ScopeOp::create(builder, scopeLoc,
1200 [&](mlir::OpBuilder &b, mlir::Location loc) {
1202 builder.getInsertionBlock()};
1203 res = doStmtBuilder();
1210 return mlir::success();
1214 cir::WhileOp whileOp;
1217 auto whileStmtBuilder = [&]() -> mlir::LogicalResult {
1218 mlir::LogicalResult loopRes = mlir::success();
1229 condVarExtendedTemporaries =
1231 bool needsCondCleanup =
1234 shouldEmitLifetimeMarkersForAutoVar() ||
1235 !condVarExtendedTemporaries.empty());
1238 auto condBuilder = [&](mlir::OpBuilder &b, mlir::Location loc) {
1244 condVarExtendedTemporaries);
1249 builder.createCondition(condVal);
1251 auto bodyBuilder = [&](mlir::OpBuilder &b, mlir::Location loc) {
1255 loopRes = mlir::failure();
1259 if (needsCondCleanup) {
1260 cir::CleanupKind cleanupKind =
getLangOpts().Exceptions
1261 ? cir::CleanupKind::All
1262 : cir::CleanupKind::Normal;
1263 whileOp = builder.createWhile(
1266 [&](mlir::OpBuilder &b, mlir::Location loc) {
1267 loopCondScope.emitIntoCleanupRegion(loc);
1268 builder.createYield(loc);
1278 mlir::LogicalResult res = mlir::success();
1280 cir::ScopeOp::create(builder, scopeLoc,
1281 [&](mlir::OpBuilder &b, mlir::Location loc) {
1283 builder.getInsertionBlock()};
1284 res = whileStmtBuilder();
1291 return mlir::success();
1311 mlir::Block *switchBlock = builder.getBlock();
1317 builder.setInsertionPointToEnd(switchBlock);
1324 auto *c = body.front();
1327 return mlir::failure();
1329 body = body.drop_front();
1335 mlir::Block *lastBlock = builder.getBlock();
1336 switchBlock = builder.createBlock(switchBlock->getParent());
1337 builder.setInsertionPointToEnd(lastBlock);
1341 for (
auto *c : body) {
1342 if (
auto *
switchCase = dyn_cast<SwitchCase>(c)) {
1343 builder.setInsertionPointToEnd(switchBlock);
1349 return mlir::failure();
1356 return mlir::failure();
1359 return mlir::success();
1370 auto switchStmtBuilder = [&]() -> mlir::LogicalResult {
1373 return mlir::failure();
1385 condV = builder.createBoolToInt(condV, builder.getUIntNTy(1));
1393 mlir::LogicalResult res = mlir::success();
1394 swop = SwitchOp::create(
1397 [&](mlir::OpBuilder &b, mlir::Location loc, mlir::OperationState &os) {
1398 curLexScope->setAsSwitch();
1400 condTypeStack.push_back(condV.getType());
1402 res = emitSwitchBody(s.getBody());
1404 condTypeStack.pop_back();
1412 mlir::LogicalResult res = mlir::success();
1413 cir::ScopeOp::create(builder, scopeLoc,
1414 [&](mlir::OpBuilder &b, mlir::Location loc) {
1416 builder.getInsertionBlock()};
1417 res = switchStmtBuilder();
1421 swop.collectCases(cases);
1422 for (
auto caseOp : cases)
1447 assert(rv.
isComplex() &&
"Unknown rvalue kind?");
1457 cir::AllocaOp retAlloca =
1458 mlir::cast<cir::AllocaOp>(
fnRetAlloca->getDefiningOp());
1459 auto value = cir::LoadOp::create(builder, loc, retAlloca.getAllocaType(),
1462 cir::ReturnOp::create(builder, loc, {value});
static mlir::LogicalResult emitStmtWithResult(CIRGenFunction &cgf, const Stmt *exprResult, AggValueSlot slot, Address *lastValue)
static clang::AtomicOptions getAdjustedAtomicOptions(clang::AtomicOptions ao, const AtomicAttr *aa)
Compute the atomic options that apply for the extent of a clang::atomic attributed statement,...
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
This file defines OpenACC AST classes for statement-level contructs.
This file defines OpenMP AST classes for executable directives and clauses.
This file defines SYCL AST classes used to represent calls to SYCL kernels.
Attr - This represents one attribute.
Represents an attribute applied to a statement.
ArrayRef< const Attr * > getAttrs() const
BreakStmt - This represents a break.
mlir::Value getPointer() const
static AggValueSlot forAddr(Address addr, clang::Qualifiers quals, IsDestructed_t isDestructed, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed)
Captures cleanups for variables whose lifetime ends in a region owned by an enclosing op rather than ...
Enters a new scope for capturing cleanups, all of which will be executed once the scope is exited.
void forceCleanup(ArrayRef< mlir::Value * > valuesToReload={})
Force the emission of cleanups now, instead of waiting until this object is destroyed.
mlir::LogicalResult emitOMPTargetParallelForDirective(const OMPTargetParallelForDirective &s)
mlir::LogicalResult emitOMPParallelMasterTaskLoopSimdDirective(const OMPParallelMasterTaskLoopSimdDirective &s)
mlir::LogicalResult emitOMPSimdDirective(const OMPSimdDirective &s)
mlir::Value emitCheckedArgForAssume(const Expr *e)
Emits an argument for a call to a __builtin_assume.
mlir::LogicalResult emitDoStmt(const clang::DoStmt &s)
mlir::LogicalResult emitOMPCriticalDirective(const OMPCriticalDirective &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...
mlir::LogicalResult emitCoreturnStmt(const CoreturnStmt &s)
mlir::LogicalResult emitOpenACCDataConstruct(const OpenACCDataConstruct &s)
EHScopeStack::stable_iterator prologueCleanupDepth
The cleanup depth enclosing all the cleanups associated with the parameters.
mlir::LogicalResult emitOpenACCCombinedConstruct(const OpenACCCombinedConstruct &s)
mlir::LogicalResult emitOMPParallelMasterDirective(const OMPParallelMasterDirective &s)
mlir::LogicalResult emitOpenACCWaitConstruct(const OpenACCWaitConstruct &s)
mlir::LogicalResult emitOMPCancellationPointDirective(const OMPCancellationPointDirective &s)
mlir::LogicalResult emitOMPParallelMaskedTaskLoopDirective(const OMPParallelMaskedTaskLoopDirective &s)
mlir::LogicalResult emitOMPReverseDirective(const OMPReverseDirective &s)
const clang::LangOptions & getLangOpts() const
mlir::LogicalResult emitOpenACCUpdateConstruct(const OpenACCUpdateConstruct &s)
mlir::LogicalResult emitOMPTileDirective(const OMPTileDirective &s)
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.
mlir::LogicalResult emitOMPTargetTeamsDirective(const OMPTargetTeamsDirective &s)
mlir::LogicalResult emitOMPTeamsDistributeParallelForDirective(const OMPTeamsDistributeParallelForDirective &s)
mlir::LogicalResult emitOMPBarrierDirective(const OMPBarrierDirective &s)
mlir::LogicalResult emitOMPTargetParallelDirective(const OMPTargetParallelDirective &s)
mlir::LogicalResult emitOpenACCCacheConstruct(const OpenACCCacheConstruct &s)
mlir::LogicalResult emitOMPTargetDirective(const OMPTargetDirective &s)
mlir::LogicalResult emitCXXForRangeStmt(const CXXForRangeStmt &s, llvm::ArrayRef< const Attr * > attrs)
mlir::Value evaluateExprAsBool(const clang::Expr *e)
Perform the usual unary conversions on the specified expression and compare the result against zero,...
void emitAggregateCopy(LValue dest, LValue src, QualType eltTy, AggValueSlot::Overlap_t mayOverlap, bool isVolatile=false)
Emit an aggregate copy.
mlir::LogicalResult emitOMPScopeDirective(const OMPScopeDirective &s)
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
mlir::LogicalResult emitOMPDepobjDirective(const OMPDepobjDirective &s)
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::LogicalResult emitReturnStmt(const clang::ReturnStmt &s)
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.
mlir::LogicalResult emitOMPDistributeParallelForSimdDirective(const OMPDistributeParallelForSimdDirective &s)
void emitLoopConditionVariable(const clang::VarDecl &d, CapturedCleanups &condCleanup, llvm::ArrayRef< QualType > extendedTemporaries)
Emit a loop's condition-variable declaration.
mlir::LogicalResult emitOMPUnrollDirective(const OMPUnrollDirective &s)
mlir::LogicalResult emitOMPTaskDirective(const OMPTaskDirective &s)
mlir::LogicalResult emitOpenACCSetConstruct(const OpenACCSetConstruct &s)
RValue emitReferenceBindingToExpr(const Expr *e)
Emits a reference binding to the passed in expression.
mlir::LogicalResult emitOMPTeamsGenericLoopDirective(const OMPTeamsGenericLoopDirective &s)
mlir::LogicalResult emitOMPCanonicalLoop(const OMPCanonicalLoop &s)
mlir::LogicalResult emitSwitchStmt(const clang::SwitchStmt &s)
mlir::LogicalResult emitOMPTeamsDirective(const OMPTeamsDirective &s)
mlir::LogicalResult emitCaseStmt(const clang::CaseStmt &s, mlir::Type condType, bool buildingTopLevelCase)
llvm::ScopedHashTableScope< const clang::Decl *, mlir::Value > SymTableScopeTy
mlir::LogicalResult emitOMPMaskedTaskLoopDirective(const OMPMaskedTaskLoopDirective &s)
mlir::LogicalResult emitOMPFuseDirective(const OMPFuseDirective &s)
mlir::LogicalResult emitSimpleStmt(const clang::Stmt *s, bool useCurrentScope)
mlir::LogicalResult emitOMPSectionDirective(const OMPSectionDirective &s)
mlir::LogicalResult emitAsmStmt(const clang::AsmStmt &s)
mlir::LogicalResult emitOMPFlattenDirective(const OMPFlattenDirective &s)
mlir::LogicalResult emitOMPParallelForSimdDirective(const OMPParallelForSimdDirective &s)
mlir::LogicalResult emitOMPDistributeParallelForDirective(const OMPDistributeParallelForDirective &s)
mlir::LogicalResult emitOMPOrderedStandaloneDirective(const OMPOrderedStandaloneDirective &s)
mlir::LogicalResult emitOpenACCComputeConstruct(const OpenACCComputeConstruct &s)
mlir::LogicalResult emitOMPMasterTaskLoopSimdDirective(const OMPMasterTaskLoopSimdDirective &s)
EHScopeStack ehStack
Tracks function scope overall cleanup handling.
mlir::LogicalResult emitSwitchBody(const clang::Stmt *s)
mlir::LogicalResult emitForStmt(const clang::ForStmt &s)
mlir::LogicalResult emitOMPTaskwaitDirective(const OMPTaskwaitDirective &s)
mlir::LogicalResult emitOMPFlushDirective(const OMPFlushDirective &s)
mlir::LogicalResult emitOMPGenericLoopDirective(const OMPGenericLoopDirective &s)
mlir::LogicalResult emitOMPTargetUpdateDirective(const OMPTargetUpdateDirective &s)
std::optional< mlir::Value > fnRetAlloca
The compiler-generated variable that holds the return value.
mlir::LogicalResult emitOMPTargetParallelForSimdDirective(const OMPTargetParallelForSimdDirective &s)
mlir::LogicalResult emitOMPInterchangeDirective(const OMPInterchangeDirective &s)
mlir::LogicalResult emitOMPDispatchDirective(const OMPDispatchDirective &s)
mlir::LogicalResult emitOMPParallelDirective(const OMPParallelDirective &s)
mlir::LogicalResult emitCXXTryStmt(const clang::CXXTryStmt &s, cxxTryBodyEmitter &bodyCallback, bool isFnTryBlock=false)
mlir::LogicalResult emitAttributedStmt(const AttributedStmt &s)
mlir::LogicalResult emitOMPForSimdDirective(const OMPForSimdDirective &s)
mlir::LogicalResult emitOMPTaskLoopDirective(const OMPTaskLoopDirective &s)
Address returnValue
The temporary alloca to hold the return value.
mlir::LogicalResult emitOMPTargetDataDirective(const OMPTargetDataDirective &s)
mlir::LogicalResult emitLabel(const clang::LabelDecl &d)
mlir::LogicalResult emitOMPTargetParallelGenericLoopDirective(const OMPTargetParallelGenericLoopDirective &s)
static bool hasAggregateEvaluationKind(clang::QualType type)
mlir::LogicalResult emitOMPParallelMaskedDirective(const OMPParallelMaskedDirective &s)
mlir::LogicalResult emitOMPMaskedTaskLoopSimdDirective(const OMPMaskedTaskLoopSimdDirective &s)
mlir::LogicalResult emitOMPAtomicDirective(const OMPAtomicDirective &s)
mlir::LogicalResult emitOpenACCShutdownConstruct(const OpenACCShutdownConstruct &s)
mlir::LogicalResult emitBreakStmt(const clang::BreakStmt &s)
mlir::LogicalResult emitIndirectGotoStmt(const IndirectGotoStmt &s)
const CallExpr * mustTailCall
mlir::LogicalResult emitOMPTeamsDistributeParallelForSimdDirective(const OMPTeamsDistributeParallelForSimdDirective &s)
mlir::LogicalResult emitOMPTaskgroupDirective(const OMPTaskgroupDirective &s)
mlir::LogicalResult emitOMPParallelMaskedTaskLoopSimdDirective(const OMPParallelMaskedTaskLoopSimdDirective &s)
mlir::LogicalResult emitOMPTeamsDistributeDirective(const OMPTeamsDistributeDirective &s)
void emitReturnOfRValue(mlir::Location loc, RValue rv, QualType ty)
mlir::LogicalResult emitOMPInteropDirective(const OMPInteropDirective &s)
mlir::LogicalResult emitOMPErrorDirective(const OMPErrorDirective &s)
mlir::LogicalResult emitOMPSingleDirective(const OMPSingleDirective &s)
bool checkIfLoopMustProgress(const clang::Expr *controllingExpression, bool hasEmptyBody)
mlir::LogicalResult emitContinueStmt(const clang::ContinueStmt &s)
mlir::LogicalResult emitOMPTaskyieldDirective(const OMPTaskyieldDirective &s)
mlir::LogicalResult emitOMPTargetTeamsDistributeSimdDirective(const OMPTargetTeamsDistributeSimdDirective &s)
mlir::LogicalResult emitOMPScanDirective(const OMPScanDirective &s)
llvm::SmallVector< mlir::Type, 2 > condTypeStack
The type of the condition for the emitting switch statement.
mlir::LogicalResult emitOMPTargetEnterDataDirective(const OMPTargetEnterDataDirective &s)
void emitStopPoint(const Stmt *s)
Build a debug stoppoint if we are emitting debug info.
mlir::LogicalResult emitOMPMasterTaskLoopDirective(const OMPMasterTaskLoopDirective &s)
mlir::LogicalResult emitOpenACCHostDataConstruct(const OpenACCHostDataConstruct &s)
mlir::Value emitScalarExpr(const clang::Expr *e, bool ignoreResultAssign=false)
Emit the computation of the specified expression of scalar type.
mlir::LogicalResult emitIfStmt(const clang::IfStmt &s)
mlir::LogicalResult emitOMPForDirective(const OMPForDirective &s)
mlir::LogicalResult emitOMPMasterDirective(const OMPMasterDirective &s)
AggValueSlot::Overlap_t getOverlapForReturnValue()
Determine whether a return value slot may overlap some other object.
mlir::LogicalResult emitSwitchCase(const clang::SwitchCase &s, bool buildingTopLevelCase)
mlir::LogicalResult emitOMPMetaDirective(const OMPMetaDirective &s)
mlir::LogicalResult emitOMPDistributeSimdDirective(const OMPDistributeSimdDirective &s)
void emitDecl(const clang::Decl &d, bool evaluateConditionDecl=false)
mlir::LogicalResult emitOMPParallelGenericLoopDirective(const OMPParallelGenericLoopDirective &s)
mlir::LogicalResult emitOMPMaskedDirective(const OMPMaskedDirective &s)
mlir::LogicalResult emitOMPSplitDirective(const OMPSplitDirective &s)
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...
CIRGenModule & getCIRGenModule()
mlir::LogicalResult emitOpenACCEnterDataConstruct(const OpenACCEnterDataConstruct &s)
mlir::LogicalResult emitOMPTargetExitDataDirective(const OMPTargetExitDataDirective &s)
bool containsLabel(const clang::Stmt *s, bool ignoreCaseStmts=false)
Return true if the statement contains a label in it.
mlir::LogicalResult emitOMPOrderedBlockAssocDirective(const OMPOrderedBlockAssocDirective &s)
mlir::LogicalResult emitOMPTargetTeamsDistributeParallelForDirective(const OMPTargetTeamsDistributeParallelForDirective &s)
void emitComplexExprIntoLValue(const Expr *e, LValue dest, bool isInit)
mlir::LogicalResult emitOMPParallelForDirective(const OMPParallelForDirective &s)
mlir::LogicalResult emitCaseDefaultCascade(const T *stmt, mlir::Type condType, mlir::ArrayAttr value, cir::CaseOpKind kind, bool buildingTopLevelCase)
mlir::LogicalResult emitOMPSectionsDirective(const OMPSectionsDirective &s)
LValue makeAddrLValue(Address addr, QualType ty, AlignmentSource source=AlignmentSource::Type)
mlir::LogicalResult emitOMPDistributeDirective(const OMPDistributeDirective &s)
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.
mlir::LogicalResult emitOMPTargetTeamsDistributeParallelForSimdDirective(const OMPTargetTeamsDistributeParallelForSimdDirective &s)
mlir::LogicalResult emitOMPTargetTeamsGenericLoopDirective(const OMPTargetTeamsGenericLoopDirective &s)
mlir::LogicalResult emitDeclStmt(const clang::DeclStmt &s)
mlir::LogicalResult emitOMPTeamsDistributeSimdDirective(const OMPTeamsDistributeSimdDirective &s)
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)
mlir::LogicalResult emitOMPTaskLoopSimdDirective(const OMPTaskLoopSimdDirective &s)
LexicalScope * curLexScope
void terminateStructuredRegionBody(mlir::Region &r, mlir::Location loc)
clang::ASTContext & getContext() const
mlir::LogicalResult emitCoroutineBody(const CoroutineBodyStmt &s)
mlir::LogicalResult emitCompoundStmt(const clang::CompoundStmt &s, Address *lastValue=nullptr, AggValueSlot slot=AggValueSlot::ignored())
mlir::LogicalResult emitGotoStmt(const clang::GotoStmt &s)
bool inAlwaysInlineAttributedStmt
True if the current statement has always_inline attribute.
bool inNoInlineAttributedStmt
True if the current statement has noinline attribute.
mlir::LogicalResult emitOMPParallelMasterTaskLoopDirective(const OMPParallelMasterTaskLoopDirective &s)
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,...
mlir::LogicalResult emitStmt(const clang::Stmt *s, bool useCurrentScope, llvm::ArrayRef< const Attr * > attrs={})
mlir::LogicalResult emitOMPCancelDirective(const OMPCancelDirective &s)
mlir::LogicalResult emitOMPStripeDirective(const OMPStripeDirective &s)
mlir::LogicalResult emitOMPTargetTeamsDistributeDirective(const OMPTargetTeamsDistributeDirective &s)
mlir::LogicalResult emitCompoundStmtWithoutScope(const clang::CompoundStmt &s, Address *lastValue=nullptr, AggValueSlot slot=AggValueSlot::ignored())
mlir::LogicalResult emitOMPParallelSectionsDirective(const OMPParallelSectionsDirective &s)
mlir::LogicalResult emitOpenACCExitDataConstruct(const OpenACCExitDataConstruct &s)
mlir::LogicalResult emitSYCLKernelCallStmt(const SYCLKernelCallStmt &s)
void emitIgnoredExpr(const clang::Expr *e)
Emit code to compute the specified expression, ignoring the result.
void emitAggExpr(const clang::Expr *e, AggValueSlot slot)
mlir::LogicalResult emitOpenACCAtomicConstruct(const OpenACCAtomicConstruct &s)
mlir::LogicalResult emitOMPTargetSimdDirective(const OMPTargetSimdDirective &s)
mlir::LogicalResult emitOMPAssumeDirective(const OMPAssumeDirective &s)
mlir::LogicalResult emitOpenACCLoopConstruct(const OpenACCLoopConstruct &s)
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
This trivial value class is used to represent the result of an expression that is evaluated.
Address getAggregateAddress() const
Return the value of the address of the aggregate.
mlir::Value getValue() const
Return the value of this scalar value.
mlir::Value getComplexValue() const
Return the value of this complex value.
CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for statement, represented as 'for (ra...
DeclStmt * getBeginStmt()
DeclStmt * getRangeStmt()
SourceLocation getEndLoc() const LLVM_READONLY
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
CaseStmt - Represent a case statement.
CompoundStmt - This represents a group of statements like { stmt stmt }.
ContinueStmt - This represents a continue.
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
DoStmt - This represents a 'do/while' stmt.
SourceLocation getEndLoc() const
This represents one expression.
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
ForStmt - This represents a 'for (init;cond;inc)' stmt.
VarDecl * getConditionVariable() const
Retrieve the variable declared in this "for" statement, if any.
SourceLocation getEndLoc() const
GotoStmt - This represents a direct goto.
LabelDecl * getLabel() const
IfStmt - This represents an if/then/else.
bool isNegatedConsteval() const
VarDecl * getConditionVariable()
Retrieve the variable declared in this "if" statement, if any.
IndirectGotoStmt - This represents an indirect goto.
Represents the declaration of a label.
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
LabelStmt - Represents a label, which has a substatement.
LabelDecl * getDecl() const
SourceLocation getKwLoc() const
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
A (possibly-)qualified type.
The collection of all-type qualifiers we support.
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
const VarDecl * getNRVOCandidate() const
Retrieve the variable that might be used for the named return value optimization.
Stmt - This represents one statement.
StmtClass getStmtClass() const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
const char * getStmtClassName() const
SwitchStmt - This represents a 'switch' stmt.
bool isAllEnumCasesCovered() const
Returns true if the SwitchStmt is a switch of an enum value and all cases have been explicitly covere...
VarDecl * getConditionVariable()
Retrieve the variable declared in this "switch" statement, if any.
SourceLocation getBeginLoc() const
Represents a variable declaration or definition.
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?
WhileStmt - This represents a 'while' stmt.
VarDecl * getConditionVariable()
Retrieve the variable declared in this "while" statement, if any.
SourceLocation getEndLoc() const LLVM_READONLY
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
bool hasEmptyLoopBody(const LoopStmt &S)
const internal::VariadicDynCastAllOfMatcher< Stmt, CompoundStmt > compoundStmt
Matches compound statements.
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const internal::VariadicDynCastAllOfMatcher< Stmt, SwitchCase > switchCase
Matches case and default statements inside switch statements.
const internal::VariadicAllOfMatcher< Stmt > stmt
Matches statements.
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
@ Default
Set to the current date and time.
const FunctionProtoType * T
U cast(CodeGen::Address addr)
@ Other
Other implicit parameter.
static bool aggValueSlotGC()
static bool createProfileWeightsForLoop()
static bool loopInfoStack()
static bool emitCondLikelihoodViaExpectIntrinsic()
static bool constantFoldSwitchStatement()
static bool insertBuiltinUnpredictable()
static bool generateDebugInfo()
static bool incrementProfileCounter()
unsigned fine_grained_memory
unsigned ignore_denormal_mode
Represents a scope, including function bodies, compound statements, and the substatements of if/while...