@@ -97,6 +97,8 @@ mlir::LogicalResult CIRGenFunction::emitStmt(const Stmt *s,
9797 return emitWhileStmt (cast<WhileStmt>(*s));
9898 case Stmt::DoStmtClass:
9999 return emitDoStmt (cast<DoStmt>(*s));
100+ case Stmt::CXXForRangeStmtClass:
101+ return emitCXXForRangeStmt (cast<CXXForRangeStmt>(*s), attr);
100102 case Stmt::OpenACCComputeConstructClass:
101103 return emitOpenACCComputeConstruct (cast<OpenACCComputeConstruct>(*s));
102104 case Stmt::OpenACCLoopConstructClass:
@@ -137,7 +139,6 @@ mlir::LogicalResult CIRGenFunction::emitStmt(const Stmt *s,
137139 case Stmt::CoroutineBodyStmtClass:
138140 case Stmt::CoreturnStmtClass:
139141 case Stmt::CXXTryStmtClass:
140- case Stmt::CXXForRangeStmtClass:
141142 case Stmt::IndirectGotoStmtClass:
142143 case Stmt::GCCAsmStmtClass:
143144 case Stmt::MSAsmStmtClass:
@@ -547,6 +548,83 @@ mlir::LogicalResult CIRGenFunction::emitSwitchCase(const SwitchCase &s,
547548 llvm_unreachable (" expect case or default stmt" );
548549}
549550
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+
550628mlir::LogicalResult CIRGenFunction::emitForStmt (const ForStmt &s) {
551629 cir::ForOp forOp;
552630
0 commit comments