[flang-commits] [flang] [flang] implement function form of SYSTEM intrinsic (PR #117585)
Tom Eccles via flang-commits
flang-commits at lists.llvm.org
Mon Nov 25 09:53:06 PST 2024
https://github.com/tblah created https://github.com/llvm/llvm-project/pull/117585
SYSTEM is a gfortran extension which we already supported in subroutine form. Gfortran also allows it to be called as a function, which was requested by a user
https://discourse.llvm.org/t/unresolved-externals-with-appendend-underscore/83305/4
>From d9a7d86629612215f3323e54b51293fac0798ddf Mon Sep 17 00:00:00 2001
From: Tom Eccles <tom.eccles at arm.com>
Date: Mon, 25 Nov 2024 17:44:48 +0000
Subject: [PATCH] [flang] implement function form of SYSTEM intrinsic
SYSTEM is a gfortran extension which we already supported in subroutine
form. Gfortran also allows it to be called as a function, which was
requested by a user
https://discourse.llvm.org/t/unresolved-externals-with-appendend-underscore/83305/4
---
.../flang/Optimizer/Builder/IntrinsicCall.h | 3 +-
flang/lib/Evaluate/intrinsics.cpp | 4 ++-
flang/lib/Optimizer/Builder/IntrinsicCall.cpp | 22 +++++++++++--
flang/test/Lower/Intrinsics/system.f90 | 32 +++++++++++++++++++
4 files changed, 56 insertions(+), 5 deletions(-)
diff --git a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h
index e83d1a42e34133..19c623cc1ec006 100644
--- a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h
+++ b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h
@@ -395,7 +395,8 @@ struct IntrinsicLibrary {
fir::ExtendedValue genSum(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
void genSignalSubroutine(llvm::ArrayRef<fir::ExtendedValue>);
void genSleep(llvm::ArrayRef<fir::ExtendedValue>);
- void genSystem(mlir::ArrayRef<fir::ExtendedValue> args);
+ fir::ExtendedValue genSystem(std::optional<mlir::Type>,
+ mlir::ArrayRef<fir::ExtendedValue> args);
void genSystemClock(llvm::ArrayRef<fir::ExtendedValue>);
mlir::Value genTand(mlir::Type, llvm::ArrayRef<mlir::Value>);
mlir::Value genTrailz(mlir::Type, llvm::ArrayRef<mlir::Value>);
diff --git a/flang/lib/Evaluate/intrinsics.cpp b/flang/lib/Evaluate/intrinsics.cpp
index 1e27c0ae4216c5..f9096a8e3f1103 100644
--- a/flang/lib/Evaluate/intrinsics.cpp
+++ b/flang/lib/Evaluate/intrinsics.cpp
@@ -884,6 +884,8 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
IntrinsicClass::transformationalFunction},
{"sum", {{"array", SameNumeric, Rank::array}, MissingDIM, OptionalMASK},
SameNumeric, Rank::scalar, IntrinsicClass::transformationalFunction},
+ {"system", {{"command", DefaultChar, Rank::scalar}}, DefaultInt,
+ Rank::scalar},
{"tan", {{"x", SameFloating}}, SameFloating},
{"tand", {{"x", SameFloating}}, SameFloating},
{"tanh", {{"x", SameFloating}}, SameFloating},
@@ -2640,7 +2642,7 @@ bool IntrinsicProcTable::Implementation::IsDualIntrinsic(
// Collection for some intrinsics with function and subroutine form,
// in order to pass the semantic check.
static const std::string dualIntrinsic[]{
- {"etime"s}, {"getcwd"s}, {"rename"s}, {"second"s}};
+ {"etime"s}, {"getcwd"s}, {"rename"s}, {"second"s}, {"system"s}};
return llvm::is_contained(dualIntrinsic, name);
}
diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
index a2b327f45c6939..08ca71699396f9 100644
--- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
+++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
@@ -7280,12 +7280,22 @@ IntrinsicLibrary::genSum(mlir::Type resultType,
}
// SYSTEM
-void IntrinsicLibrary::genSystem(llvm::ArrayRef<fir::ExtendedValue> args) {
- assert(args.size() == 2);
+fir::ExtendedValue
+IntrinsicLibrary::genSystem(std::optional<mlir::Type> resultType,
+ llvm::ArrayRef<fir::ExtendedValue> args) {
+ assert((!resultType && (args.size() == 2)) ||
+ (resultType && (args.size() == 1)));
mlir::Value command = fir::getBase(args[0]);
- const fir::ExtendedValue &exitstat = args[1];
assert(command && "expected COMMAND parameter");
+ fir::ExtendedValue exitstat;
+ if (resultType) {
+ mlir::Value tmp = builder.createTemporary(loc, *resultType);
+ exitstat = builder.createBox(loc, tmp);
+ } else {
+ exitstat = args[1];
+ }
+
mlir::Type boxNoneTy = fir::BoxType::get(builder.getNoneType());
mlir::Value waitBool = builder.createBool(loc, true);
@@ -7307,6 +7317,12 @@ void IntrinsicLibrary::genSystem(llvm::ArrayRef<fir::ExtendedValue> args) {
fir::runtime::genExecuteCommandLine(builder, loc, command, waitBool,
exitstatBox, cmdstatBox, cmdmsgBox);
+
+ if (resultType) {
+ mlir::Value exitstatAddr = builder.create<fir::BoxAddrOp>(loc, exitstatBox);
+ return builder.create<fir::LoadOp>(loc, fir::getBase(exitstatAddr));
+ }
+ return {};
}
// SYSTEM_CLOCK
diff --git a/flang/test/Lower/Intrinsics/system.f90 b/flang/test/Lower/Intrinsics/system.f90
index 71655938113f77..87ac8d9c7e6f95 100644
--- a/flang/test/Lower/Intrinsics/system.f90
+++ b/flang/test/Lower/Intrinsics/system.f90
@@ -51,3 +51,35 @@ subroutine only_command(command)
! CHECK-NEXT: return
! CHECK-NEXT: }
end subroutine only_command
+
+! CHECK-LABEL: func.func @_QPas_function(
+! CHECK-SAME: %[[commandArg:.*]]: !fir.boxchar<1> {fir.bindc_name = "command"}
+subroutine as_function(command)
+CHARACTER(*) :: command
+INTEGER :: exitstat
+exitstat = system(command)
+end subroutine
+! CHECK-NEXT: %[[cmdstatVal:.*]] = fir.alloca i16
+! CHECK-NEXT: %[[RETVAL:.*]] = fir.alloca i32
+! CHECK-NEXT: %[[DSCOPE:.*]] = fir.dummy_scope : !fir.dscope
+! CHECK-NEXT: %[[commandUnbox:.*]]:2 = fir.unboxchar %[[commandArg]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
+! CHECK-NEXT: %[[commandDeclare:.*]]:2 = hlfir.declare %[[commandUnbox]]#0 typeparams %[[commandUnbox]]#1 dummy_scope %[[DSCOPE]] {uniq_name = "_QFas_functionEcommand"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
+! CHECK-NEXT: %[[EXITSTAT_ALLOC:.*]] = fir.alloca i32
+! CHECK-NEXT: %[[exitstatDeclare:.*]]:2 = hlfir.declare %[[EXITSTAT_ALLOC]] {uniq_name = "_QFas_functionEexitstat"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK-NEXT: %[[commandBox:.*]] = fir.embox %[[commandDeclare]]#1 typeparams %[[commandUnbox]]#1 : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>>
+! CHECK-NEXT: %[[exitstatBox:.*]] = fir.embox %[[RETVAL]] : (!fir.ref<i32>) -> !fir.box<i32>
+! CHECK-NEXT: %[[true:.*]] = arith.constant true
+! CHECK-NEXT: %[[c0_i16:.*]] = arith.constant 0 : i16
+! CHECK-NEXT: fir.store %[[c0_i16]] to %[[cmdstatVal]] : !fir.ref<i16>
+! CHECK-NEXT: %[[cmdstatBox:.*]] = fir.embox %[[cmdstatVal]] : (!fir.ref<i16>) -> !fir.box<i16>
+! CHECK-NEXT: %[[absentBox:.*]] = fir.absent !fir.box<none>
+! CHECK: %[[LINE_NO:.*]] = arith.constant {{.*}} : i32
+! CHECK-NEXT: %[[command:.*]] = fir.convert %[[commandBox]] : (!fir.box<!fir.char<1,?>>) -> !fir.box<none>
+! CHECK-NEXT: %[[exitstat:.*]] = fir.convert %[[exitstatBox]] : (!fir.box<i32>) -> !fir.box<none>
+! CHECK-NEXT: %[[cmdstat:.*]] = fir.convert %[[cmdstatBox]] : (!fir.box<i16>) -> !fir.box<none>
+! CHECK: %[[VAL_13:.*]] = fir.call @_FortranAExecuteCommandLine(%[[command]], %[[true]], %[[exitstat]], %[[cmdstat]], %[[absentBox]], %[[VAL_12:.*]], %[[LINE_NO]]) fastmath<contract> : (!fir.box<none>, i1, !fir.box<none>, !fir.box<none>, !fir.box<none>, !fir.ref<i8>, i32) -> none
+! CHECK-NEXT: %[[RET_ADDR:.*]] = fir.box_addr %[[exitstatBox]] : (!fir.box<i32>) -> !fir.ref<i32>
+! CHECK-NEXT: %[[RET:.*]] = fir.load %[[RET_ADDR]] : !fir.ref<i32>
+! CHECK-NEXT: hlfir.assign %[[RET]] to %[[exitstatDeclare]]#0 : i32, !fir.ref<i32>
+! CHECK-NEXT: return
+! CHECK-NEXT: }
More information about the flang-commits
mailing list