[flang-commits] [flang] db48f7b - [flang] Lower IO open and close statements

Valentin Clement via flang-commits flang-commits at lists.llvm.org
Wed Mar 2 08:57:17 PST 2022


Author: Valentin Clement
Date: 2022-03-02T17:57:08+01:00
New Revision: db48f7b2f7b3a3a62822bd41de84b9ccb6093b5f

URL: https://github.com/llvm/llvm-project/commit/db48f7b2f7b3a3a62822bd41de84b9ccb6093b5f
DIFF: https://github.com/llvm/llvm-project/commit/db48f7b2f7b3a3a62822bd41de84b9ccb6093b5f.diff

LOG: [flang] Lower IO open and close statements

This patch adds the lowering of open and close statements

This patch is part of the upstreaming effort from fir-dev branch.

Reviewed By: schweitz

Differential Revision: https://reviews.llvm.org/D120821

Co-authored-by: Jean Perier <jperier at nvidia.com>

Added: 
    

Modified: 
    flang/include/flang/Lower/IO.h
    flang/lib/Lower/Bridge.cpp
    flang/lib/Lower/IO.cpp
    flang/test/Lower/io-statement-1.f90

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Lower/IO.h b/flang/include/flang/Lower/IO.h
index 9d5c007cbc35e..f2acb7af3fb85 100644
--- a/flang/include/flang/Lower/IO.h
+++ b/flang/include/flang/Lower/IO.h
@@ -19,6 +19,8 @@ class Value;
 
 namespace Fortran {
 namespace parser {
+struct CloseStmt;
+struct OpenStmt;
 struct ReadStmt;
 struct PrintStmt;
 struct WriteStmt;
@@ -28,10 +30,16 @@ namespace lower {
 
 class AbstractConverter;
 
+/// Generate IO call(s) for CLOSE; return the IOSTAT code
+mlir::Value genCloseStatement(AbstractConverter &, const parser::CloseStmt &);
+
 /// Generate IO call(s) for READ; return the IOSTAT code
 mlir::Value genReadStatement(AbstractConverter &converter,
                              const parser::ReadStmt &stmt);
 
+/// Generate IO call(s) for OPEN; return the IOSTAT code
+mlir::Value genOpenStatement(AbstractConverter &, const parser::OpenStmt &);
+
 /// Generate IO call(s) for PRINT
 void genPrintStatement(AbstractConverter &converter,
                        const parser::PrintStmt &stmt);

diff  --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index 6a3e8244bd5ba..7af503fa30bec 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -815,7 +815,8 @@ class FirConverter : public Fortran::lower::AbstractConverter {
   }
 
   void genFIR(const Fortran::parser::CloseStmt &stmt) {
-    TODO(toLocation(), "CloseStmt lowering");
+    mlir::Value iostat = genCloseStatement(*this, stmt);
+    genIoConditionBranches(getEval(), stmt.v, iostat);
   }
 
   void genFIR(const Fortran::parser::EndfileStmt &stmt) {
@@ -831,7 +832,8 @@ class FirConverter : public Fortran::lower::AbstractConverter {
   }
 
   void genFIR(const Fortran::parser::OpenStmt &stmt) {
-    TODO(toLocation(), "OpenStmt lowering");
+    mlir::Value iostat = genOpenStatement(*this, stmt);
+    genIoConditionBranches(getEval(), stmt.v, iostat);
   }
 
   void genFIR(const Fortran::parser::PrintStmt &stmt) {

diff  --git a/flang/lib/Lower/IO.cpp b/flang/lib/Lower/IO.cpp
index 7b396e6e305b0..c25f6d97feb63 100644
--- a/flang/lib/Lower/IO.cpp
+++ b/flang/lib/Lower/IO.cpp
@@ -1059,6 +1059,20 @@ static bool hasX(const A &list) {
   return false;
 }
 
+template <typename SEEK, typename A>
+static bool hasMem(const A &stmt) {
+  return hasX<SEEK>(stmt.v);
+}
+
+/// Get the sought expression from the specifier list.
+template <typename SEEK, typename A>
+static const Fortran::lower::SomeExpr *getExpr(const A &stmt) {
+  for (const auto &spec : stmt.v)
+    if (auto *f = std::get_if<SEEK>(&spec.u))
+      return Fortran::semantics::GetExpr(f->v);
+  llvm::report_fatal_error("must have a file unit");
+}
+
 /// For each specifier, build the appropriate call, threading the cookie.
 template <typename A>
 static void threadSpecs(Fortran::lower::AbstractConverter &converter,
@@ -1469,6 +1483,77 @@ mlir::Value getIOUnit(Fortran::lower::AbstractConverter &converter,
       loc, builder.getIntegerAttr(ty, Fortran::runtime::io::DefaultUnit));
 }
 
+//===----------------------------------------------------------------------===//
+// Generators for each IO statement type.
+//===----------------------------------------------------------------------===//
+
+template <typename K, typename S>
+static mlir::Value genBasicIOStmt(Fortran::lower::AbstractConverter &converter,
+                                  const S &stmt) {
+  fir::FirOpBuilder &builder = converter.getFirOpBuilder();
+  Fortran::lower::StatementContext stmtCtx;
+  mlir::Location loc = converter.getCurrentLocation();
+  mlir::FuncOp beginFunc = getIORuntimeFunc<K>(loc, builder);
+  mlir::FunctionType beginFuncTy = beginFunc.getType();
+  mlir::Value unit = fir::getBase(converter.genExprValue(
+      getExpr<Fortran::parser::FileUnitNumber>(stmt), stmtCtx, loc));
+  mlir::Value un = builder.createConvert(loc, beginFuncTy.getInput(0), unit);
+  mlir::Value file = locToFilename(converter, loc, beginFuncTy.getInput(1));
+  mlir::Value line = locToLineNo(converter, loc, beginFuncTy.getInput(2));
+  auto call = builder.create<fir::CallOp>(loc, beginFunc,
+                                          mlir::ValueRange{un, file, line});
+  mlir::Value cookie = call.getResult(0);
+  ConditionSpecInfo csi;
+  genConditionHandlerCall(converter, loc, cookie, stmt.v, csi);
+  mlir::Value ok;
+  auto insertPt = builder.saveInsertionPoint();
+  threadSpecs(converter, loc, cookie, stmt.v, csi.hasErrorConditionSpec(), ok);
+  builder.restoreInsertionPoint(insertPt);
+  return genEndIO(converter, converter.getCurrentLocation(), cookie, csi,
+                  stmtCtx);
+}
+
+mlir::Value
+Fortran::lower::genOpenStatement(Fortran::lower::AbstractConverter &converter,
+                                 const Fortran::parser::OpenStmt &stmt) {
+  fir::FirOpBuilder &builder = converter.getFirOpBuilder();
+  Fortran::lower::StatementContext stmtCtx;
+  mlir::FuncOp beginFunc;
+  llvm::SmallVector<mlir::Value> beginArgs;
+  mlir::Location loc = converter.getCurrentLocation();
+  if (hasMem<Fortran::parser::FileUnitNumber>(stmt)) {
+    beginFunc = getIORuntimeFunc<mkIOKey(BeginOpenUnit)>(loc, builder);
+    mlir::FunctionType beginFuncTy = beginFunc.getType();
+    mlir::Value unit = fir::getBase(converter.genExprValue(
+        getExpr<Fortran::parser::FileUnitNumber>(stmt), stmtCtx, loc));
+    beginArgs.push_back(
+        builder.createConvert(loc, beginFuncTy.getInput(0), unit));
+    beginArgs.push_back(locToFilename(converter, loc, beginFuncTy.getInput(1)));
+    beginArgs.push_back(locToLineNo(converter, loc, beginFuncTy.getInput(2)));
+  } else {
+    assert(hasMem<Fortran::parser::ConnectSpec::Newunit>(stmt));
+    beginFunc = getIORuntimeFunc<mkIOKey(BeginOpenNewUnit)>(loc, builder);
+    mlir::FunctionType beginFuncTy = beginFunc.getType();
+    beginArgs.push_back(locToFilename(converter, loc, beginFuncTy.getInput(0)));
+    beginArgs.push_back(locToLineNo(converter, loc, beginFuncTy.getInput(1)));
+  }
+  auto cookie =
+      builder.create<fir::CallOp>(loc, beginFunc, beginArgs).getResult(0);
+  ConditionSpecInfo csi;
+  genConditionHandlerCall(converter, loc, cookie, stmt.v, csi);
+  mlir::Value ok;
+  auto insertPt = builder.saveInsertionPoint();
+  threadSpecs(converter, loc, cookie, stmt.v, csi.hasErrorConditionSpec(), ok);
+  builder.restoreInsertionPoint(insertPt);
+  return genEndIO(converter, loc, cookie, csi, stmtCtx);
+}
+
+mlir::Value
+Fortran::lower::genCloseStatement(Fortran::lower::AbstractConverter &converter,
+                                  const Fortran::parser::CloseStmt &stmt) {
+  return genBasicIOStmt<mkIOKey(BeginClose)>(converter, stmt);
+}
+
 //===----------------------------------------------------------------------===//
 // Data transfer statements.
 //

diff  --git a/flang/test/Lower/io-statement-1.f90 b/flang/test/Lower/io-statement-1.f90
index f13612e20b0b0..3eeed9c8561a3 100644
--- a/flang/test/Lower/io-statement-1.f90
+++ b/flang/test/Lower/io-statement-1.f90
@@ -6,6 +6,12 @@
  real :: a(100)
 
   ! CHECK-LABEL: _QQmain
+  ! CHECK: call {{.*}}BeginOpenUnit
+  ! CHECK-DAG: call {{.*}}SetFile
+  ! CHECK-DAG: call {{.*}}SetAccess
+  ! CHECK: call {{.*}}EndIoStatement
+  open(8, file="foo", access="sequential")
+
   ! CHECK: call {{.*}}BeginExternalListInput
   ! CHECK: call {{.*}}InputInteger
   ! CHECK: call {{.*}}InputReal32
@@ -18,6 +24,10 @@
   ! CHECK: call {{.*}}EndIoStatement
   write (8,*) i, f
 
+  ! CHECK: call {{.*}}BeginClose
+  ! CHECK: call {{.*}}EndIoStatement
+  close(8)
+
   ! CHECK: call {{.*}}BeginExternalListOutput
   ! CHECK: call {{.*}}OutputAscii
   ! CHECK: call {{.*}}EndIoStatement


        


More information about the flang-commits mailing list