Skip to content

Commit c0192a0

Browse files
authored
[flang] implement function form of SYSTEM intrinsic (#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
1 parent ad7bb65 commit c0192a0

File tree

4 files changed

+56
-5
lines changed

4 files changed

+56
-5
lines changed

flang/include/flang/Optimizer/Builder/IntrinsicCall.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,8 @@ struct IntrinsicLibrary {
395395
fir::ExtendedValue genSum(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
396396
void genSignalSubroutine(llvm::ArrayRef<fir::ExtendedValue>);
397397
void genSleep(llvm::ArrayRef<fir::ExtendedValue>);
398-
void genSystem(mlir::ArrayRef<fir::ExtendedValue> args);
398+
fir::ExtendedValue genSystem(std::optional<mlir::Type>,
399+
mlir::ArrayRef<fir::ExtendedValue> args);
399400
void genSystemClock(llvm::ArrayRef<fir::ExtendedValue>);
400401
mlir::Value genTand(mlir::Type, llvm::ArrayRef<mlir::Value>);
401402
mlir::Value genTrailz(mlir::Type, llvm::ArrayRef<mlir::Value>);

flang/lib/Evaluate/intrinsics.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -885,6 +885,8 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
885885
IntrinsicClass::transformationalFunction},
886886
{"sum", {{"array", SameNumeric, Rank::array}, MissingDIM, OptionalMASK},
887887
SameNumeric, Rank::scalar, IntrinsicClass::transformationalFunction},
888+
{"system", {{"command", DefaultChar, Rank::scalar}}, DefaultInt,
889+
Rank::scalar},
888890
{"tan", {{"x", SameFloating}}, SameFloating},
889891
{"tand", {{"x", SameFloating}}, SameFloating},
890892
{"tanh", {{"x", SameFloating}}, SameFloating},
@@ -2641,7 +2643,7 @@ bool IntrinsicProcTable::Implementation::IsDualIntrinsic(
26412643
// Collection for some intrinsics with function and subroutine form,
26422644
// in order to pass the semantic check.
26432645
static const std::string dualIntrinsic[]{
2644-
{"etime"s}, {"getcwd"s}, {"rename"s}, {"second"s}};
2646+
{"etime"s}, {"getcwd"s}, {"rename"s}, {"second"s}, {"system"s}};
26452647

26462648
return llvm::is_contained(dualIntrinsic, name);
26472649
}

flang/lib/Optimizer/Builder/IntrinsicCall.cpp

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7281,12 +7281,22 @@ IntrinsicLibrary::genSum(mlir::Type resultType,
72817281
}
72827282

72837283
// SYSTEM
7284-
void IntrinsicLibrary::genSystem(llvm::ArrayRef<fir::ExtendedValue> args) {
7285-
assert(args.size() == 2);
7284+
fir::ExtendedValue
7285+
IntrinsicLibrary::genSystem(std::optional<mlir::Type> resultType,
7286+
llvm::ArrayRef<fir::ExtendedValue> args) {
7287+
assert((!resultType && (args.size() == 2)) ||
7288+
(resultType && (args.size() == 1)));
72867289
mlir::Value command = fir::getBase(args[0]);
7287-
const fir::ExtendedValue &exitstat = args[1];
72887290
assert(command && "expected COMMAND parameter");
72897291

7292+
fir::ExtendedValue exitstat;
7293+
if (resultType) {
7294+
mlir::Value tmp = builder.createTemporary(loc, *resultType);
7295+
exitstat = builder.createBox(loc, tmp);
7296+
} else {
7297+
exitstat = args[1];
7298+
}
7299+
72907300
mlir::Type boxNoneTy = fir::BoxType::get(builder.getNoneType());
72917301

72927302
mlir::Value waitBool = builder.createBool(loc, true);
@@ -7308,6 +7318,12 @@ void IntrinsicLibrary::genSystem(llvm::ArrayRef<fir::ExtendedValue> args) {
73087318

73097319
fir::runtime::genExecuteCommandLine(builder, loc, command, waitBool,
73107320
exitstatBox, cmdstatBox, cmdmsgBox);
7321+
7322+
if (resultType) {
7323+
mlir::Value exitstatAddr = builder.create<fir::BoxAddrOp>(loc, exitstatBox);
7324+
return builder.create<fir::LoadOp>(loc, fir::getBase(exitstatAddr));
7325+
}
7326+
return {};
73117327
}
73127328

73137329
// SYSTEM_CLOCK

flang/test/Lower/Intrinsics/system.f90

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,35 @@ subroutine only_command(command)
5151
! CHECK-NEXT: return
5252
! CHECK-NEXT: }
5353
end subroutine only_command
54+
55+
! CHECK-LABEL: func.func @_QPas_function(
56+
! CHECK-SAME: %[[commandArg:.*]]: !fir.boxchar<1> {fir.bindc_name = "command"}
57+
subroutine as_function(command)
58+
CHARACTER(*) :: command
59+
INTEGER :: exitstat
60+
exitstat = system(command)
61+
end subroutine
62+
! CHECK-NEXT: %[[cmdstatVal:.*]] = fir.alloca i16
63+
! CHECK-NEXT: %[[RETVAL:.*]] = fir.alloca i32
64+
! CHECK-NEXT: %[[DSCOPE:.*]] = fir.dummy_scope : !fir.dscope
65+
! CHECK-NEXT: %[[commandUnbox:.*]]:2 = fir.unboxchar %[[commandArg]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
66+
! 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,?>>)
67+
! CHECK-NEXT: %[[EXITSTAT_ALLOC:.*]] = fir.alloca i32
68+
! CHECK-NEXT: %[[exitstatDeclare:.*]]:2 = hlfir.declare %[[EXITSTAT_ALLOC]] {uniq_name = "_QFas_functionEexitstat"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
69+
! CHECK-NEXT: %[[commandBox:.*]] = fir.embox %[[commandDeclare]]#1 typeparams %[[commandUnbox]]#1 : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>>
70+
! CHECK-NEXT: %[[exitstatBox:.*]] = fir.embox %[[RETVAL]] : (!fir.ref<i32>) -> !fir.box<i32>
71+
! CHECK-NEXT: %[[true:.*]] = arith.constant true
72+
! CHECK-NEXT: %[[c0_i16:.*]] = arith.constant 0 : i16
73+
! CHECK-NEXT: fir.store %[[c0_i16]] to %[[cmdstatVal]] : !fir.ref<i16>
74+
! CHECK-NEXT: %[[cmdstatBox:.*]] = fir.embox %[[cmdstatVal]] : (!fir.ref<i16>) -> !fir.box<i16>
75+
! CHECK-NEXT: %[[absentBox:.*]] = fir.absent !fir.box<none>
76+
! CHECK: %[[LINE_NO:.*]] = arith.constant {{.*}} : i32
77+
! CHECK-NEXT: %[[command:.*]] = fir.convert %[[commandBox]] : (!fir.box<!fir.char<1,?>>) -> !fir.box<none>
78+
! CHECK-NEXT: %[[exitstat:.*]] = fir.convert %[[exitstatBox]] : (!fir.box<i32>) -> !fir.box<none>
79+
! CHECK-NEXT: %[[cmdstat:.*]] = fir.convert %[[cmdstatBox]] : (!fir.box<i16>) -> !fir.box<none>
80+
! 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
81+
! CHECK-NEXT: %[[RET_ADDR:.*]] = fir.box_addr %[[exitstatBox]] : (!fir.box<i32>) -> !fir.ref<i32>
82+
! CHECK-NEXT: %[[RET:.*]] = fir.load %[[RET_ADDR]] : !fir.ref<i32>
83+
! CHECK-NEXT: hlfir.assign %[[RET]] to %[[exitstatDeclare]]#0 : i32, !fir.ref<i32>
84+
! CHECK-NEXT: return
85+
! CHECK-NEXT: }

0 commit comments

Comments
 (0)