@@ -97,6 +97,8 @@ mlir::LogicalResult CIRGenFunction::emitStmt(const Stmt *s,
97
97
return emitWhileStmt (cast<WhileStmt>(*s));
98
98
case Stmt::DoStmtClass:
99
99
return emitDoStmt (cast<DoStmt>(*s));
100
+ case Stmt::CXXForRangeStmtClass:
101
+ return emitCXXForRangeStmt (cast<CXXForRangeStmt>(*s), attr);
100
102
case Stmt::OpenACCComputeConstructClass:
101
103
return emitOpenACCComputeConstruct (cast<OpenACCComputeConstruct>(*s));
102
104
case Stmt::OpenACCLoopConstructClass:
@@ -137,7 +139,6 @@ mlir::LogicalResult CIRGenFunction::emitStmt(const Stmt *s,
137
139
case Stmt::CoroutineBodyStmtClass:
138
140
case Stmt::CoreturnStmtClass:
139
141
case Stmt::CXXTryStmtClass:
140
- case Stmt::CXXForRangeStmtClass:
141
142
case Stmt::IndirectGotoStmtClass:
142
143
case Stmt::GCCAsmStmtClass:
143
144
case Stmt::MSAsmStmtClass:
@@ -547,6 +548,83 @@ mlir::LogicalResult CIRGenFunction::emitSwitchCase(const SwitchCase &s,
547
548
llvm_unreachable (" expect case or default stmt" );
548
549
}
549
550
551
+ mlir::LogicalResult
552
+ CIRGenFunction::emitCXXForRangeStmt (const CXXForRangeStmt &s,
553
+ ArrayRef<const Attr *> forAttrs) {
554
+ cir::ForOp forOp;
555
+
556
+ // TODO(cir): pass in array of attributes.
557
+ auto forStmtBuilder = [&]() -> mlir::LogicalResult {
558
+ mlir::LogicalResult loopRes = mlir::success ();
559
+ // Evaluate the first pieces before the loop.
560
+ if (s.getInit ())
561
+ if (emitStmt (s.getInit (), /* useCurrentScope=*/ true ).failed ())
562
+ return mlir::failure ();
563
+ if (emitStmt (s.getRangeStmt (), /* useCurrentScope=*/ true ).failed ())
564
+ return mlir::failure ();
565
+ if (emitStmt (s.getBeginStmt (), /* useCurrentScope=*/ true ).failed ())
566
+ return mlir::failure ();
567
+ if (emitStmt (s.getEndStmt (), /* useCurrentScope=*/ true ).failed ())
568
+ return mlir::failure ();
569
+
570
+ assert (!cir::MissingFeatures::loopInfoStack ());
571
+ // From LLVM: if there are any cleanups between here and the loop-exit
572
+ // scope, create a block to stage a loop exit along.
573
+ // We probably already do the right thing because of ScopeOp, but make
574
+ // sure we handle all cases.
575
+ assert (!cir::MissingFeatures::requiresCleanups ());
576
+
577
+ forOp = builder.createFor (
578
+ getLoc (s.getSourceRange ()),
579
+ /* condBuilder=*/
580
+ [&](mlir::OpBuilder &b, mlir::Location loc) {
581
+ assert (!cir::MissingFeatures::createProfileWeightsForLoop ());
582
+ assert (!cir::MissingFeatures::emitCondLikelihoodViaExpectIntrinsic ());
583
+ mlir::Value condVal = evaluateExprAsBool (s.getCond ());
584
+ builder.createCondition (condVal);
585
+ },
586
+ /* bodyBuilder=*/
587
+ [&](mlir::OpBuilder &b, mlir::Location loc) {
588
+ // https://en.cppreference.com/w/cpp/language/for
589
+ // In C++ the scope of the init-statement and the scope of
590
+ // statement are one and the same.
591
+ bool useCurrentScope = true ;
592
+ if (emitStmt (s.getLoopVarStmt (), useCurrentScope).failed ())
593
+ loopRes = mlir::failure ();
594
+ if (emitStmt (s.getBody (), useCurrentScope).failed ())
595
+ loopRes = mlir::failure ();
596
+ emitStopPoint (&s);
597
+ },
598
+ /* stepBuilder=*/
599
+ [&](mlir::OpBuilder &b, mlir::Location loc) {
600
+ if (s.getInc ())
601
+ if (emitStmt (s.getInc (), /* useCurrentScope=*/ true ).failed ())
602
+ loopRes = mlir::failure ();
603
+ builder.createYield (loc);
604
+ });
605
+ return loopRes;
606
+ };
607
+
608
+ mlir::LogicalResult res = mlir::success ();
609
+ mlir::Location scopeLoc = getLoc (s.getSourceRange ());
610
+ builder.create <cir::ScopeOp>(scopeLoc, /* scopeBuilder=*/
611
+ [&](mlir::OpBuilder &b, mlir::Location loc) {
612
+ // Create a cleanup scope for the condition
613
+ // variable cleanups. Logical equivalent from
614
+ // LLVM codegn for LexicalScope
615
+ // ConditionScope(*this, S.getSourceRange())...
616
+ LexicalScope lexScope{
617
+ *this , loc, builder.getInsertionBlock ()};
618
+ res = forStmtBuilder ();
619
+ });
620
+
621
+ if (res.failed ())
622
+ return res;
623
+
624
+ terminateBody (builder, forOp.getBody (), getLoc (s.getEndLoc ()));
625
+ return mlir::success ();
626
+ }
627
+
550
628
mlir::LogicalResult CIRGenFunction::emitForStmt (const ForStmt &s) {
551
629
cir::ForOp forOp;
552
630
0 commit comments