[flang-commits] [flang] [flang] Keep a LOGICAL input item unchanged on big-endian targets (PR #228588)
MMS IT GmbH via flang-commits
flang-commits at lists.llvm.org
Sat Oct 3 01:38:00 PDT 2026
https://github.com/mms-it-ch updated https://github.com/llvm/llvm-project/pull/228588
>From 32759409617a749e4189489c359ccd80fc601d9c Mon Sep 17 00:00:00 2001
From: mms-it-ch <info at mms-it.ch>
Date: Fri, 2 Oct 2026 22:49:24 +0200
Subject: [PATCH 1/2] [flang] Keep a LOGICAL input item unchanged on big-endian
targets
A scalar LOGICAL input item is passed to the runtime as a bool&, and after
the call its first byte is read back and stored into the whole LOGICAL.
If the runtime does not set the item (a null value in list-directed or
namelist input), the old value must be kept. On big-endian targets the
first byte of a LOGICAL(4) .TRUE. is zero, so the value became .FALSE.
Store the current value as a bool into the first byte before the call.
Assisted-by: Claude Code (Anthropic)
---
flang/lib/Lower/IO.cpp | 23 ++++++++++++++++++++--
flang/test/Lower/io-logical-null-input.f90 | 22 +++++++++++++++++++++
2 files changed, 43 insertions(+), 2 deletions(-)
create mode 100644 flang/test/Lower/io-logical-null-input.f90
diff --git a/flang/lib/Lower/IO.cpp b/flang/lib/Lower/IO.cpp
index 5636f9e25b9909..fef22a305a4256 100644
--- a/flang/lib/Lower/IO.cpp
+++ b/flang/lib/Lower/IO.cpp
@@ -1132,6 +1132,22 @@ static void boolRefToLogical(mlir::Location loc, fir::FirOpBuilder &builder,
fir::StoreOp::create(builder, loc, logicalValue, addr);
}
+/// Store the current value of a LOGICAL as a `bool` into the first byte of its
+/// storage before passing it to the runtime as a `bool&`. If the runtime does
+/// not set it (e.g. a null value in list-directed or namelist input), the
+/// following boolRefToLogical then keeps the old value. Without this, the old
+/// value would be lost on big-endian targets, where the first byte of a
+/// LOGICAL(4) .TRUE. is zero.
+static void logicalToBoolRef(mlir::Location loc, fir::FirOpBuilder &builder,
+ mlir::Value addr) {
+ auto logicalValue = fir::LoadOp::create(builder, loc, addr);
+ auto boolValue =
+ builder.createConvert(loc, builder.getI1Type(), logicalValue);
+ auto boolAddr = builder.createConvert(
+ loc, builder.getRefType(builder.getI1Type()), addr);
+ fir::StoreOp::create(builder, loc, boolValue, boolAddr);
+}
+
static mlir::Value
createIoRuntimeCallForItem(Fortran::lower::AbstractConverter &converter,
mlir::Location loc, mlir::func::FuncOp inputFunc,
@@ -1167,10 +1183,13 @@ createIoRuntimeCallForItem(Fortran::lower::AbstractConverter &converter,
mlir::cast<mlir::IntegerType>(itemTy).getWidth() / 8)));
}
}
- auto call = fir::CallOp::create(builder, loc, inputFunc, inputFuncArgs);
auto itemAddr = fir::getBase(item);
auto itemTy = fir::unwrapRefType(itemAddr.getType());
- if (mlir::isa<fir::LogicalType>(itemTy))
+ bool isLogical = mlir::isa<fir::LogicalType>(itemTy);
+ if (isLogical)
+ logicalToBoolRef(loc, builder, itemAddr);
+ auto call = fir::CallOp::create(builder, loc, inputFunc, inputFuncArgs);
+ if (isLogical)
boolRefToLogical(loc, builder, itemAddr);
return call.getResult(0);
}
diff --git a/flang/test/Lower/io-logical-null-input.f90 b/flang/test/Lower/io-logical-null-input.f90
new file mode 100644
index 00000000000000..47d3ed6556522d
--- /dev/null
+++ b/flang/test/Lower/io-logical-null-input.f90
@@ -0,0 +1,22 @@
+! A LOGICAL input item is passed to the runtime as a bool&. Its current value
+! is stored as a bool before the call, so that it is kept when the runtime does
+! not set it (null value in list-directed or namelist input). Otherwise the old
+! value would be lost on big-endian targets, where the first byte of a
+! LOGICAL(4) .TRUE. is zero.
+! RUN: %flang_fc1 -emit-hlfir %s -o - | FileCheck %s
+
+! CHECK-LABEL: func.func @_QPread_logical(
+subroutine read_logical(l)
+ logical :: l
+ read (*, *) l
+end subroutine
+! CHECK: %[[L:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFread_logicalEl"}
+! CHECK: %[[ARG:.*]] = fir.convert %[[L]]#0 : (!fir.ref<!fir.logical<4>>) -> !fir.ref<i1>
+! CHECK: %[[OLD:.*]] = fir.load %[[L]]#0 : !fir.ref<!fir.logical<4>>
+! CHECK: %[[B:.*]] = fir.convert %[[OLD]] : (!fir.logical<4>) -> i1
+! CHECK: %[[BA:.*]] = fir.convert %[[L]]#0 : (!fir.ref<!fir.logical<4>>) -> !fir.ref<i1>
+! CHECK: fir.store %[[B]] to %[[BA]] : !fir.ref<i1>
+! CHECK: fir.call @_FortranAioInputLogical(%{{.*}}, %[[ARG]])
+! CHECK: %[[NEW:.*]] = fir.load %{{.*}} : !fir.ref<i1>
+! CHECK: %[[V:.*]] = fir.convert %[[NEW]] : (i1) -> !fir.logical<4>
+! CHECK: fir.store %[[V]] to %[[L]]#0 : !fir.ref<!fir.logical<4>>
>From dbc4b790ce3f96a5a191989149987a9f14a50eed Mon Sep 17 00:00:00 2001
From: mms-it-ch <info at mms-it.ch>
Date: Sat, 3 Oct 2026 10:37:45 +0200
Subject: [PATCH 2/2] Format with clang-format; match both hlfir.declare
syntaxes in the test
Assisted-by: Claude Code (Anthropic)
---
flang/lib/Lower/IO.cpp | 4 ++--
flang/test/Lower/io-logical-null-input.f90 | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/flang/lib/Lower/IO.cpp b/flang/lib/Lower/IO.cpp
index fef22a305a4256..c9a00e79ab92af 100644
--- a/flang/lib/Lower/IO.cpp
+++ b/flang/lib/Lower/IO.cpp
@@ -1143,8 +1143,8 @@ static void logicalToBoolRef(mlir::Location loc, fir::FirOpBuilder &builder,
auto logicalValue = fir::LoadOp::create(builder, loc, addr);
auto boolValue =
builder.createConvert(loc, builder.getI1Type(), logicalValue);
- auto boolAddr = builder.createConvert(
- loc, builder.getRefType(builder.getI1Type()), addr);
+ auto boolAddr =
+ builder.createConvert(loc, builder.getRefType(builder.getI1Type()), addr);
fir::StoreOp::create(builder, loc, boolValue, boolAddr);
}
diff --git a/flang/test/Lower/io-logical-null-input.f90 b/flang/test/Lower/io-logical-null-input.f90
index 47d3ed6556522d..d49a569e862028 100644
--- a/flang/test/Lower/io-logical-null-input.f90
+++ b/flang/test/Lower/io-logical-null-input.f90
@@ -10,7 +10,7 @@ subroutine read_logical(l)
logical :: l
read (*, *) l
end subroutine
-! CHECK: %[[L:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFread_logicalEl"}
+! CHECK: %[[L:.*]]:2 = hlfir.declare {{.*}}"_QFread_logicalEl"
! CHECK: %[[ARG:.*]] = fir.convert %[[L]]#0 : (!fir.ref<!fir.logical<4>>) -> !fir.ref<i1>
! CHECK: %[[OLD:.*]] = fir.load %[[L]]#0 : !fir.ref<!fir.logical<4>>
! CHECK: %[[B:.*]] = fir.convert %[[OLD]] : (!fir.logical<4>) -> i1
More information about the flang-commits
mailing list