1 //===-- Command.cpp -- generate command line runtime API calls ------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "flang/Optimizer/Builder/Runtime/Command.h"
10 #include "flang/Optimizer/Builder/FIRBuilder.h"
11 #include "flang/Optimizer/Builder/Runtime/RTBuilder.h"
12 #include "flang/Runtime/command.h"
13 
14 using namespace Fortran::runtime;
15 
16 mlir::Value fir::runtime::genCommandArgumentCount(fir::FirOpBuilder &builder,
17                                                   mlir::Location loc) {
18   auto argumentCountFunc =
19       fir::runtime::getRuntimeFunc<mkRTKey(ArgumentCount)>(loc, builder);
20   return builder.create<fir::CallOp>(loc, argumentCountFunc).getResult(0);
21 }
22 
23 void fir::runtime::genGetCommandArgument(fir::FirOpBuilder &builder,
24                                          mlir::Location loc, mlir::Value number,
25                                          mlir::Value value, mlir::Value length,
26                                          mlir::Value status,
27                                          mlir::Value errmsg) {
28   auto argumentValueFunc =
29       fir::runtime::getRuntimeFunc<mkRTKey(ArgumentValue)>(loc, builder);
30   auto argumentLengthFunc =
31       fir::runtime::getRuntimeFunc<mkRTKey(ArgumentLength)>(loc, builder);
32 
33   auto isPresent = [&](mlir::Value val) -> bool {
34     return !mlir::isa_and_nonnull<fir::AbsentOp>(val.getDefiningOp());
35   };
36 
37   mlir::Value valueResult;
38   // Run `ArgumentValue` intrisc only if we have either "value", "status" or
39   // "errmsg" `ArgumentValue` "requires" existing values for its arguments
40   // "value" and "errmsg". So in the case they aren't given, but the user has
41   // requested "status", we have to assign "absent" values to them before
42   // calling `ArgumentValue`. This happens in IntrinsicCall.cpp. For this reason
43   // we need extra indirection with `isPresent` for testing whether "value" or
44   // "errmsg" is present.
45   if (isPresent(value) || status || isPresent(errmsg)) {
46     llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
47         builder, loc, argumentValueFunc.getType(), number, value, errmsg);
48     valueResult =
49         builder.create<fir::CallOp>(loc, argumentValueFunc, args).getResult(0);
50   }
51 
52   // Only save result of ArgumentValue if "status" parameter has been given
53   if (status) {
54     const mlir::Value statusLoaded = builder.create<fir::LoadOp>(loc, status);
55     mlir::Value resultCast =
56         builder.createConvert(loc, statusLoaded.getType(), valueResult);
57     builder.create<fir::StoreOp>(loc, resultCast, status);
58   }
59 
60   if (length) {
61     llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
62         builder, loc, argumentLengthFunc.getType(), number);
63     mlir::Value result =
64         builder.create<fir::CallOp>(loc, argumentLengthFunc, args).getResult(0);
65     const mlir::Value valueLoaded = builder.create<fir::LoadOp>(loc, length);
66     mlir::Value resultCast =
67         builder.createConvert(loc, valueLoaded.getType(), result);
68     builder.create<fir::StoreOp>(loc, resultCast, length);
69   }
70 }
71