diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -337,6 +337,13 @@ void genFIRProcedureExit(Fortran::lower::pft::FunctionLikeUnit &funit, const Fortran::semantics::Symbol &symbol) { + if (mlir::Block *finalBlock = funit.finalBlock) { + // The current block must end with a terminator. + if (blockIsUnterminated()) + builder->create(toLocation(), finalBlock); + // Set insertion point to final block. + builder->setInsertionPoint(finalBlock, finalBlock->end()); + } if (Fortran::semantics::IsFunction(symbol)) { TODO(toLocation(), "Function lowering"); } else { @@ -652,7 +659,24 @@ } void genFIR(const Fortran::parser::ReturnStmt &stmt) { - TODO(toLocation(), "ReturnStmt lowering"); + Fortran::lower::pft::FunctionLikeUnit *funit = + getEval().getOwningProcedure(); + assert(funit && "not inside main program, function or subroutine"); + if (funit->isMainProgram()) { + genExitRoutine(); + return; + } + mlir::Location loc = toLocation(); + if (stmt.v) { + TODO(loc, "Alternate return statement"); + } + // Branch to the last block of the SUBROUTINE, which has the actual return. + if (!funit->finalBlock) { + mlir::OpBuilder::InsertPoint insPt = builder->saveInsertionPoint(); + funit->finalBlock = builder->createBlock(&builder->getRegion()); + builder->restoreInsertionPoint(insPt); + } + builder->create(loc, funit->finalBlock); } void genFIR(const Fortran::parser::CycleStmt &) { diff --git a/flang/test/Lower/return-statement.f90 b/flang/test/Lower/return-statement.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Lower/return-statement.f90 @@ -0,0 +1,34 @@ +! RUN: bbc %s -o "-" -emit-fir | FileCheck %s + +program basic + return +end program + +! CHECK-LABEL: func @_QQmain() { +! CHECK: return +! CHECK: } + +subroutine sub1() + return +end + +! CHECK-LABEL: func @_QPsub1() { +! CHECK: cf.br ^bb1 +! CHECK: ^bb1: // pred: ^bb0 +! CHECK: return + +subroutine sub2() + goto 3 + 2 return + 3 goto 2 +end + +! CHECK-LABEL: func @_QPsub2() { +! CHECK: cf.br ^bb2 +! CHECK: ^bb1: // pred: ^bb2 +! CHECK: cf.br ^bb3 +! CHECK: ^bb2: // pred: ^bb0 +! CHECK: cf.br ^bb1 +! CHECK: ^bb3: // pred: ^bb1 +! CHECK: return +