jpenix-quic created this revision.
jpenix-quic added reviewers: schweitz, klausler, peixin, awarzynski.
jpenix-quic added a project: Flang.
Herald added subscribers: mehdi_amini, jdoerfert, mgorny.
Herald added a reviewer: sscalpone.
Herald added a project: All.
jpenix-quic requested review of this revision.
Herald added subscribers: cfe-commits, sstefan1, MaskRay.
Herald added a reviewer: jdoerfert.
Herald added a project: clang.

This follows gfortran's approach of generating a runtime call to set
the conversion state for the entire program and takes effect only if
the fconvert option is used on the main program (as the runtime call
is inserted into _QQmain).

Resolves issue: https://github.com/llvm/llvm-project/issues/55961


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D130513

Files:
  clang/include/clang/Driver/Options.td
  clang/lib/Driver/ToolChains/Flang.cpp
  flang/include/flang/Frontend/FrontendOptions.h
  flang/include/flang/Lower/Bridge.h
  flang/include/flang/Optimizer/Builder/Runtime/Convert.h
  flang/include/flang/Runtime/convert.h
  flang/include/flang/Runtime/main.h
  flang/lib/Frontend/CompilerInvocation.cpp
  flang/lib/Frontend/FrontendActions.cpp
  flang/lib/Lower/Bridge.cpp
  flang/lib/Optimizer/Builder/CMakeLists.txt
  flang/lib/Optimizer/Builder/Runtime/Convert.cpp
  flang/runtime/environment.cpp
  flang/runtime/environment.h
  flang/runtime/main.cpp
  flang/test/Driver/convert.f90
  flang/test/Driver/driver-help-hidden.f90
  flang/test/Driver/driver-help.f90
  flang/test/Driver/frontend-forwarding.f90
  flang/tools/bbc/bbc.cpp
  flang/unittests/Runtime/ExternalIOTest.cpp

Index: flang/unittests/Runtime/ExternalIOTest.cpp
===================================================================
--- flang/unittests/Runtime/ExternalIOTest.cpp
+++ flang/unittests/Runtime/ExternalIOTest.cpp
@@ -149,6 +149,67 @@
       << "EndIoStatement() for Close";
 }
 
+TEST(ExternalIOTests, TestDirectUnformattedSwappedConvert) {
+  // OPEN(NEWUNIT=unit,ACCESS='DIRECT',ACTION='READWRITE',&
+  //   FORM='UNFORMATTED',RECL=8,STATUS='SCRATCH',CONVERT='NATIVE')
+  auto *io{IONAME(BeginOpenNewUnit)(__FILE__, __LINE__)};
+  ASSERT_TRUE(IONAME(SetAccess)(io, "DIRECT", 6)) << "SetAccess(DIRECT)";
+  ASSERT_TRUE(IONAME(SetAction)(io, "READWRITE", 9)) << "SetAction(READWRITE)";
+  ASSERT_TRUE(IONAME(SetForm)(io, "UNFORMATTED", 11)) << "SetForm(UNFORMATTED)";
+  ASSERT_TRUE(IONAME(SetConvert)(io, "NATIVE", 6)) << "SetConvert(NATIVE)";
+
+  std::int64_t buffer;
+  static constexpr std::size_t recl{sizeof buffer};
+  ASSERT_TRUE(IONAME(SetRecl)(io, recl)) << "SetRecl()";
+  ASSERT_TRUE(IONAME(SetStatus)(io, "SCRATCH", 7)) << "SetStatus(SCRATCH)";
+
+  int unit{-1};
+  ASSERT_TRUE(IONAME(GetNewUnit)(io, unit)) << "GetNewUnit()";
+  ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
+      << "EndIoStatement() for OpenNewUnit";
+
+  static constexpr int records{10};
+  for (int j{1}; j <= records; ++j) {
+    // WRITE(UNIT=unit,REC=j) j
+    io = IONAME(BeginUnformattedOutput)(unit, __FILE__, __LINE__);
+    ASSERT_TRUE(IONAME(SetRec)(io, j)) << "SetRec(" << j << ')';
+    buffer = j;
+    ASSERT_TRUE(IONAME(OutputUnformattedBlock)(
+        io, reinterpret_cast<const char *>(&buffer), recl, recl))
+        << "OutputUnformattedBlock()";
+    ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
+        << "EndIoStatement() for OutputUnformattedBlock";
+  }
+
+  // Set unformatted conversion to SWAP
+  RTNAME(ConvertOption)(4);
+  // OPEN(UNIT=unit,STATUS='OLD')
+  io = IONAME(BeginOpenUnit)(unit, __FILE__, __LINE__);
+  ASSERT_TRUE(IONAME(SetStatus)(io, "OLD", 3)) << "SetStatus(OLD)";
+  ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
+      << "EndIoStatement() for OpenUnit";
+
+  for (int j{records}; j >= 1; --j) {
+    // READ(UNIT=unit,REC=j) n
+    io = IONAME(BeginUnformattedInput)(unit, __FILE__, __LINE__);
+    ASSERT_TRUE(IONAME(SetRec)(io, j)) << "SetRec(" << j << ')';
+    ASSERT_TRUE(IONAME(InputUnformattedBlock)(
+        io, reinterpret_cast<char *>(&buffer), recl, recl))
+        << "InputUnformattedBlock()";
+    ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
+        << "EndIoStatement() for InputUnformattedBlock";
+    ASSERT_EQ(buffer >> 56, j)
+        << "Read back " << (buffer >> 56) << " from direct unformatted record "
+        << j << ", expected " << j << '\n';
+  }
+
+  // CLOSE(UNIT=unit,STATUS='DELETE')
+  io = IONAME(BeginClose)(unit, __FILE__, __LINE__);
+  ASSERT_TRUE(IONAME(SetStatus)(io, "DELETE", 6)) << "SetStatus(DELETE)";
+  ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
+      << "EndIoStatement() for Close";
+}
+
 TEST(ExternalIOTests, TestSequentialFixedUnformatted) {
   // OPEN(NEWUNIT=unit,ACCESS='SEQUENTIAL',ACTION='READWRITE',&
   //   FORM='UNFORMATTED',RECL=8,STATUS='SCRATCH')
Index: flang/tools/bbc/bbc.cpp
===================================================================
--- flang/tools/bbc/bbc.cpp
+++ flang/tools/bbc/bbc.cpp
@@ -33,6 +33,7 @@
 #include "flang/Parser/parsing.h"
 #include "flang/Parser/provenance.h"
 #include "flang/Parser/unparse.h"
+#include "flang/Runtime/convert.h"
 #include "flang/Semantics/expression.h"
 #include "flang/Semantics/runtime-type-info.h"
 #include "flang/Semantics/semantics.h"
@@ -219,7 +220,7 @@
   auto burnside = Fortran::lower::LoweringBridge::create(
       ctx, defKinds, semanticsContext.intrinsics(),
       semanticsContext.targetCharacteristics(), parsing.allCooked(), "",
-      kindMap);
+      kindMap, Fortran::runtime::Convert::Unknown);
   burnside.lower(parseTree, semanticsContext);
   mlir::ModuleOp mlirModule = burnside.getModule();
   std::error_code ec;
Index: flang/test/Driver/frontend-forwarding.f90
===================================================================
--- flang/test/Driver/frontend-forwarding.f90
+++ flang/test/Driver/frontend-forwarding.f90
@@ -7,6 +7,7 @@
 ! RUN:     -fdefault-integer-8 \
 ! RUN:     -fdefault-real-8 \
 ! RUN:     -flarge-sizes \
+! RUN:     -fconvert=little-endian \
 ! RUN:     -mllvm -print-before-all\
 ! RUN:     -P \
 ! RUN:   | FileCheck %s
@@ -17,4 +18,5 @@
 ! CHECK: "-fdefault-integer-8"
 ! CHECK: "-fdefault-real-8"
 ! CHECK: "-flarge-sizes"
+! CHECK: "-fconvert=little-endian"
 ! CHECK:  "-mllvm" "-print-before-all"
Index: flang/test/Driver/driver-help.f90
===================================================================
--- flang/test/Driver/driver-help.f90
+++ flang/test/Driver/driver-help.f90
@@ -24,6 +24,7 @@
 ! HELP-NEXT: Enable the old style PARAMETER statement
 ! HELP-NEXT: -fbackslash            Specify that backslash in string introduces an escape character
 ! HELP-NEXT: -fcolor-diagnostics    Enable colors in diagnostics
+! HELP-NEXT: -fconvert=<value>       Set endian conversion of data for unformatted files
 ! HELP-NEXT: -fdefault-double-8     Set the default double precision kind to an 8 byte wide type
 ! HELP-NEXT: -fdefault-integer-8    Set the default integer kind to an 8 byte wide type
 ! HELP-NEXT: -fdefault-real-8       Set the default real kind to an 8 byte wide type
@@ -78,6 +79,7 @@
 ! HELP-FC1-NEXT: Enable the old style PARAMETER statement
 ! HELP-FC1-NEXT: -fbackslash            Specify that backslash in string introduces an escape character
 ! HELP-FC1-NEXT: -fcolor-diagnostics     Enable colors in diagnostics
+! HELP-FC1-NEXT: -fconvert=<value>       Set endian conversion of data for unformatted files
 ! HELP-FC1-NEXT: -fdebug-dump-all       Dump symbols and the parse tree after the semantic checks
 ! HELP-FC1-NEXT: -fdebug-dump-parse-tree-no-sema
 ! HELP-FC1-NEXT:                        Dump the parse tree (skips the semantic checks)
Index: flang/test/Driver/driver-help-hidden.f90
===================================================================
--- flang/test/Driver/driver-help-hidden.f90
+++ flang/test/Driver/driver-help-hidden.f90
@@ -24,6 +24,7 @@
 ! CHECK-NEXT: Enable the old style PARAMETER statement
 ! CHECK-NEXT: -fbackslash            Specify that backslash in string introduces an escape character
 ! CHECK-NEXT: -fcolor-diagnostics    Enable colors in diagnostics
+! CHECK-NEXT: -fconvert=<value>       Set endian conversion of data for unformatted files
 ! CHECK-NEXT: -fdefault-double-8     Set the default double precision kind to an 8 byte wide type
 ! CHECK-NEXT: -fdefault-integer-8    Set the default integer kind to an 8 byte wide type
 ! CHECK-NEXT: -fdefault-real-8       Set the default real kind to an 8 byte wide type
Index: flang/test/Driver/convert.f90
===================================================================
--- /dev/null
+++ flang/test/Driver/convert.f90
@@ -0,0 +1,13 @@
+! Ensure argument -fconvert=<value> works as expected.
+
+!--------------------------
+! FLANG DRIVER (flang)
+!--------------------------
+! RUN: not %flang -fconvert=foobar %s  2>&1 | FileCheck %s --check-prefix=WRONG
+
+!!-----------------------------------------
+! FRONTEND FLANG DRIVER (flang-new -fc1)
+!-----------------------------------------
+! RUN: not %flang_fc1 -fconvert=foobar %s  2>&1 | FileCheck %s --check-prefix=WRONG
+
+! WRONG: error: invalid value 'foobar' in '-fconvert=foobar'
Index: flang/runtime/main.cpp
===================================================================
--- flang/runtime/main.cpp
+++ flang/runtime/main.cpp
@@ -43,4 +43,19 @@
         Fortran::runtime::Convert::Swap;
   }
 }
+
+void RTNAME(ConvertOption)(int i) {
+  // Defer to the current conversion value to allow the environment variable to
+  // take precedence even if the command-line option was specified.
+  if (Fortran::runtime::executionEnvironment.conversion !=
+      Fortran::runtime::Convert::Unknown)
+    return;
+
+  if (auto convert{Fortran::runtime::GetConvertFromInt(i)}) {
+    Fortran::runtime::executionEnvironment.conversion = *convert;
+  } else {
+    Fortran::runtime::Terminator{__FILE__, __LINE__}.Crash(
+        "Invalid convert option passed to ConvertOption");
+  }
+}
 }
Index: flang/runtime/environment.h
===================================================================
--- flang/runtime/environment.h
+++ flang/runtime/environment.h
@@ -10,6 +10,7 @@
 #define FORTRAN_RUNTIME_ENVIRONMENT_H_
 
 #include "flang/Decimal/decimal.h"
+#include "flang/Runtime/convert.h"
 #include <optional>
 
 namespace Fortran::runtime {
@@ -24,10 +25,8 @@
 #error host endianness is not known
 #endif
 
-// External unformatted I/O data conversions
-enum class Convert { Unknown, Native, LittleEndian, BigEndian, Swap };
-
 std::optional<Convert> GetConvertFromString(const char *, std::size_t);
+std::optional<Convert> GetConvertFromInt(int);
 
 struct ExecutionEnvironment {
   constexpr ExecutionEnvironment(){};
Index: flang/runtime/environment.cpp
===================================================================
--- flang/runtime/environment.cpp
+++ flang/runtime/environment.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "environment.h"
+#include "flang/Runtime/convert.h"
 #include "memory.h"
 #include "tools.h"
 #include <cstdio>
@@ -37,6 +38,15 @@
   }
 }
 
+std::optional<Convert> GetConvertFromInt(int i) {
+  if (i < static_cast<int>(Convert::Unknown) ||
+      i > static_cast<int>(Convert::Swap)) {
+    return std::nullopt;
+  }
+
+  return static_cast<Convert>(i);
+}
+
 void ExecutionEnvironment::Configure(
     int ac, const char *av[], const char *env[]) {
   argc = ac;
Index: flang/lib/Optimizer/Builder/Runtime/Convert.cpp
===================================================================
--- /dev/null
+++ flang/lib/Optimizer/Builder/Runtime/Convert.cpp
@@ -0,0 +1,26 @@
+//===-- Convert.cpp -------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "flang/Optimizer/Builder/Runtime/Convert.h"
+#include "flang/Optimizer/Builder/FIRBuilder.h"
+#include "flang/Optimizer/Builder/Runtime/RTBuilder.h"
+#include "flang/Runtime/convert.h"
+#include "flang/Runtime/main.h"
+
+void fir::runtime::genConvertOption(mlir::Location loc,
+                                    fir::FirOpBuilder &builder,
+                                    Fortran::runtime::Convert conversion) {
+  mlir::func::FuncOp func =
+      fir::runtime::getRuntimeFunc<mkRTKey(ConvertOption)>(loc, builder);
+  mlir::FunctionType funcTy = func.getFunctionType();
+  mlir::Value conversionVal = builder.createIntegerConstant(
+      loc, funcTy.getInput(0), static_cast<int>(conversion));
+  llvm::SmallVector<mlir::Value> args =
+      fir::runtime::createArguments(builder, loc, funcTy, conversionVal);
+  builder.create<fir::CallOp>(loc, func, args);
+}
Index: flang/lib/Optimizer/Builder/CMakeLists.txt
===================================================================
--- flang/lib/Optimizer/Builder/CMakeLists.txt
+++ flang/lib/Optimizer/Builder/CMakeLists.txt
@@ -11,6 +11,7 @@
   Runtime/Assign.cpp
   Runtime/Character.cpp
   Runtime/Command.cpp
+  Runtime/Convert.cpp
   Runtime/Derived.cpp
   Runtime/Inquiry.cpp
   Runtime/Numeric.cpp
Index: flang/lib/Lower/Bridge.cpp
===================================================================
--- flang/lib/Lower/Bridge.cpp
+++ flang/lib/Lower/Bridge.cpp
@@ -31,6 +31,8 @@
 #include "flang/Optimizer/Builder/Character.h"
 #include "flang/Optimizer/Builder/FIRBuilder.h"
 #include "flang/Optimizer/Builder/Runtime/Character.h"
+#include "flang/Optimizer/Builder/Runtime/Convert.h"
+#include "flang/Optimizer/Builder/Runtime/RTBuilder.h"
 #include "flang/Optimizer/Builder/Runtime/Ragged.h"
 #include "flang/Optimizer/Builder/Todo.h"
 #include "flang/Optimizer/Dialect/FIRAttr.h"
@@ -41,6 +43,7 @@
 #include "flang/Optimizer/Support/InternalNames.h"
 #include "flang/Optimizer/Transforms/Passes.h"
 #include "flang/Parser/parse-tree.h"
+#include "flang/Runtime/convert.h"
 #include "flang/Runtime/iostat.h"
 #include "flang/Semantics/tools.h"
 #include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
@@ -2752,6 +2755,12 @@
       builder->create<fir::StoreOp>(loc, zero, altResult);
     }
 
+    if (funit.isMainProgram()) {
+      auto conversion = bridge.getConversion();
+      if (conversion != Fortran::runtime::Convert::Unknown)
+        fir::runtime::genConvertOption(toLocation(), *builder, conversion);
+    }
+
     if (Fortran::lower::pft::Evaluation *alternateEntryEval =
             funit.getEntryEval())
       genFIRBranch(alternateEntryEval->lexicalSuccessor->block);
@@ -3217,10 +3226,10 @@
     const Fortran::evaluate::IntrinsicProcTable &intrinsics,
     const Fortran::evaluate::TargetCharacteristics &targetCharacteristics,
     const Fortran::parser::AllCookedSources &cooked, llvm::StringRef triple,
-    fir::KindMapping &kindMap)
+    fir::KindMapping &kindMap, Fortran::runtime::Convert conversion)
     : defaultKinds{defaultKinds}, intrinsics{intrinsics},
       targetCharacteristics{targetCharacteristics}, cooked{&cooked},
-      context{context}, kindMap{kindMap} {
+      context{context}, kindMap{kindMap}, conversion{conversion} {
   // Register the diagnostic handler.
   context.getDiagEngine().registerHandler([](mlir::Diagnostic &diag) {
     llvm::raw_ostream &os = llvm::errs();
Index: flang/lib/Frontend/FrontendActions.cpp
===================================================================
--- flang/lib/Frontend/FrontendActions.cpp
+++ flang/lib/Frontend/FrontendActions.cpp
@@ -148,7 +148,7 @@
       *mlirCtx, defKinds, ci.getInvocation().getSemanticsContext().intrinsics(),
       ci.getInvocation().getSemanticsContext().targetCharacteristics(),
       ci.getParsing().allCooked(), ci.getInvocation().getTargetOpts().triple,
-      kindMap);
+      kindMap, ci.getInvocation().getFrontendOpts().conversion);
 
   // Create a parse tree and lower it to FIR
   Fortran::parser::Program &parseTree{*ci.getParsing().parseTree()};
Index: flang/lib/Frontend/CompilerInvocation.cpp
===================================================================
--- flang/lib/Frontend/CompilerInvocation.cpp
+++ flang/lib/Frontend/CompilerInvocation.cpp
@@ -15,6 +15,7 @@
 #include "flang/Frontend/CodeGenOptions.h"
 #include "flang/Frontend/PreprocessorOptions.h"
 #include "flang/Frontend/TargetOptions.h"
+#include "flang/Runtime/convert.h"
 #include "flang/Semantics/semantics.h"
 #include "flang/Version.inc"
 #include "clang/Basic/AllDiagnostics.h"
@@ -366,6 +367,27 @@
     }
   }
 
+  // Set conversion based on -fconvert=<value>
+  if (const auto *arg =
+          args.getLastArg(clang::driver::options::OPT_fconvert_EQ)) {
+    auto parseConvert = [](const char *s) {
+      return llvm::StringSwitch<std::optional<Fortran::runtime::Convert>>(s)
+          .Case("unknown", Fortran::runtime::Convert::Unknown)
+          .Case("native", Fortran::runtime::Convert::Native)
+          .Case("little-endian", Fortran::runtime::Convert::LittleEndian)
+          .Case("big-endian", Fortran::runtime::Convert::BigEndian)
+          .Case("swap", Fortran::runtime::Convert::Swap)
+          .Default(std::nullopt);
+    };
+
+    const char *argValue = arg->getValue();
+    if (auto convert = parseConvert(argValue))
+      opts.conversion = *convert;
+    else
+      diags.Report(clang::diag::err_drv_invalid_value)
+          << arg->getAsString(args) << argValue;
+  }
+
   // -f{no-}implicit-none
   opts.features.Enable(
       Fortran::common::LanguageFeature::ImplicitNoneTypeAlways,
Index: flang/include/flang/Runtime/main.h
===================================================================
--- flang/include/flang/Runtime/main.h
+++ flang/include/flang/Runtime/main.h
@@ -15,6 +15,7 @@
 FORTRAN_EXTERN_C_BEGIN
 void RTNAME(ProgramStart)(int, const char *[], const char *[]);
 void RTNAME(ByteswapOption)(void); // -byteswapio
+void RTNAME(ConvertOption)(int);   // -fconvert
 FORTRAN_EXTERN_C_END
 
 #endif // FORTRAN_RUNTIME_MAIN_H_
Index: flang/include/flang/Runtime/convert.h
===================================================================
--- /dev/null
+++ flang/include/flang/Runtime/convert.h
@@ -0,0 +1,18 @@
+//===-- Runtime/convert.h ---------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef FORTRAN_RUNTIME_RAGGED_H_
+#define FORTRAN_RUNTIME_RAGGED_H_
+
+namespace Fortran::runtime {
+
+// External unformatted I/O data conversions
+enum class Convert { Unknown, Native, LittleEndian, BigEndian, Swap };
+
+} // namespace Fortran::runtime
+#endif // FORTRAN_RUNTIME_RAGGED_H_
Index: flang/include/flang/Optimizer/Builder/Runtime/Convert.h
===================================================================
--- /dev/null
+++ flang/include/flang/Optimizer/Builder/Runtime/Convert.h
@@ -0,0 +1,32 @@
+//===-- Convert.h -----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef FORTRAN_OPTIMIZER_BUILDER_RUNTIME_CONVERT_H
+#define FORTRAN_OPTIMIZER_BUILDER_RUNTIME_CONVERT_H
+
+namespace mlir {
+class Location;
+} // namespace mlir
+
+namespace fir {
+class FirOpBuilder;
+} // namespace fir
+
+namespace Fortran::runtime {
+enum class Convert;
+} // namespace Fortran::runtime
+
+namespace fir::runtime {
+
+/// Generate a call to the runtime routine to set the endian conversion for
+/// unformatted files to the mode specified by \p conversion.
+void genConvertOption(mlir::Location loc, fir::FirOpBuilder &builder,
+                      Fortran::runtime::Convert conversion);
+
+} // namespace fir::runtime
+#endif // FORTRAN_OPTIMIZER_BUILDER_RUNTIME_CONVERT_H
Index: flang/include/flang/Lower/Bridge.h
===================================================================
--- flang/include/flang/Lower/Bridge.h
+++ flang/include/flang/Lower/Bridge.h
@@ -34,6 +34,9 @@
 namespace semantics {
 class SemanticsContext;
 } // namespace semantics
+namespace runtime {
+enum class Convert;
+} // namespace runtime
 
 namespace lower {
 
@@ -52,9 +55,10 @@
          const Fortran::evaluate::IntrinsicProcTable &intrinsics,
          const Fortran::evaluate::TargetCharacteristics &targetCharacteristics,
          const Fortran::parser::AllCookedSources &allCooked,
-         llvm::StringRef triple, fir::KindMapping &kindMap) {
+         llvm::StringRef triple, fir::KindMapping &kindMap,
+         Fortran::runtime::Convert conversion) {
     return LoweringBridge(ctx, defaultKinds, intrinsics, targetCharacteristics,
-                          allCooked, triple, kindMap);
+                          allCooked, triple, kindMap, conversion);
   }
 
   //===--------------------------------------------------------------------===//
@@ -83,6 +87,8 @@
   /// Get the kind map.
   const fir::KindMapping &getKindMap() const { return kindMap; }
 
+  Fortran::runtime::Convert getConversion() const { return conversion; }
+
   /// Create a folding context. Careful: this is very expensive.
   Fortran::evaluate::FoldingContext createFoldingContext() const;
 
@@ -107,7 +113,7 @@
       const Fortran::evaluate::IntrinsicProcTable &intrinsics,
       const Fortran::evaluate::TargetCharacteristics &targetCharacteristics,
       const Fortran::parser::AllCookedSources &cooked, llvm::StringRef triple,
-      fir::KindMapping &kindMap);
+      fir::KindMapping &kindMap, Fortran::runtime::Convert conversion);
   LoweringBridge() = delete;
   LoweringBridge(const LoweringBridge &) = delete;
 
@@ -118,6 +124,7 @@
   mlir::MLIRContext &context;
   std::unique_ptr<mlir::ModuleOp> module;
   fir::KindMapping &kindMap;
+  const Fortran::runtime::Convert conversion;
 };
 
 } // namespace lower
Index: flang/include/flang/Frontend/FrontendOptions.h
===================================================================
--- flang/include/flang/Frontend/FrontendOptions.h
+++ flang/include/flang/Frontend/FrontendOptions.h
@@ -16,6 +16,7 @@
 #include "flang/Common/Fortran-features.h"
 #include "flang/Parser/characters.h"
 #include "flang/Parser/unparse.h"
+#include "flang/Runtime/convert.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include <cstdint>
@@ -258,6 +259,9 @@
   // The form to process files in, if specified.
   FortranForm fortranForm = FortranForm::Unknown;
 
+  // Conversion to apply to unformatted IO, if specified.
+  Fortran::runtime::Convert conversion = Fortran::runtime::Convert::Unknown;
+
   // The column after which characters are ignored in fixed form lines in the
   // source file.
   int fixedFormColumns = 72;
Index: clang/lib/Driver/ToolChains/Flang.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Flang.cpp
+++ clang/lib/Driver/ToolChains/Flang.cpp
@@ -29,19 +29,27 @@
 
 void Flang::AddFortranDialectOptions(const ArgList &Args,
                                      ArgStringList &CmdArgs) const {
-  Args.AddAllArgs(
-      CmdArgs, {options::OPT_ffixed_form, options::OPT_ffree_form,
-                options::OPT_ffixed_line_length_EQ, options::OPT_fopenmp,
-                options::OPT_fopenacc, options::OPT_finput_charset_EQ,
-                options::OPT_fimplicit_none, options::OPT_fno_implicit_none,
-                options::OPT_fbackslash, options::OPT_fno_backslash,
-                options::OPT_flogical_abbreviations,
-                options::OPT_fno_logical_abbreviations,
-                options::OPT_fxor_operator, options::OPT_fno_xor_operator,
-                options::OPT_falternative_parameter_statement,
-                options::OPT_fdefault_real_8, options::OPT_fdefault_integer_8,
-                options::OPT_fdefault_double_8, options::OPT_flarge_sizes,
-                options::OPT_fno_automatic});
+  Args.AddAllArgs(CmdArgs, {options::OPT_ffixed_form,
+                            options::OPT_ffree_form,
+                            options::OPT_ffixed_line_length_EQ,
+                            options::OPT_fopenmp,
+                            options::OPT_fopenacc,
+                            options::OPT_finput_charset_EQ,
+                            options::OPT_fimplicit_none,
+                            options::OPT_fno_implicit_none,
+                            options::OPT_fbackslash,
+                            options::OPT_fno_backslash,
+                            options::OPT_flogical_abbreviations,
+                            options::OPT_fno_logical_abbreviations,
+                            options::OPT_fxor_operator,
+                            options::OPT_fno_xor_operator,
+                            options::OPT_falternative_parameter_statement,
+                            options::OPT_fdefault_real_8,
+                            options::OPT_fdefault_integer_8,
+                            options::OPT_fdefault_double_8,
+                            options::OPT_flarge_sizes,
+                            options::OPT_fno_automatic,
+                            options::OPT_fconvert_EQ});
 }
 
 void Flang::AddPreprocessingOptions(const ArgList &Args,
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -4794,7 +4794,6 @@
 def fblas_matmul_limit_EQ : Joined<["-"], "fblas-matmul-limit=">, Group<gfortran_Group>;
 def fcheck_EQ : Joined<["-"], "fcheck=">, Group<gfortran_Group>;
 def fcoarray_EQ : Joined<["-"], "fcoarray=">, Group<gfortran_Group>;
-def fconvert_EQ : Joined<["-"], "fconvert=">, Group<gfortran_Group>;
 def ffpe_trap_EQ : Joined<["-"], "ffpe-trap=">, Group<gfortran_Group>;
 def ffree_line_length_VALUE : Joined<["-"], "ffree-line-length-">, Group<gfortran_Group>;
 def finit_character_EQ : Joined<["-"], "finit-character=">, Group<gfortran_Group>;
@@ -4895,6 +4894,8 @@
   DocBrief<[{Set column after which characters are ignored in typical fixed-form lines in the source
 file}]>;
 def ffixed_line_length_VALUE : Joined<["-"], "ffixed-line-length-">, Group<f_Group>, Alias<ffixed_line_length_EQ>;
+def fconvert_EQ : Joined<["-"], "fconvert=">, Group<f_Group>,
+  HelpText<"Set endian conversion of data for unformatted files">;
 def fopenacc : Flag<["-"], "fopenacc">, Group<f_Group>,
   HelpText<"Enable OpenACC">;
 def fdefault_double_8 : Flag<["-"],"fdefault-double-8">, Group<f_Group>,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to