Handle dynamic optional argument in GET_COMMAND_ARGUMENT and GET_ENVIRONMENT_VARIABLE
(previously compiled but caused segfaults). The previous code
handled static presence/absence aspects, but not when an absent dummy optional was
passed to one of the optional intrinsic arguments.
Simplify the runtime call lowering to simply lower the runtime call without
dealing with optionality there. This keeps the optional handling logic in
IntrinsicCall.cpp.
Note that the new code will generate some extra "if (not null addr )/then/else"
when the actual arguments are always there at runtime. That makes the implementation
a lot simpler/safer, and I think it is OK for now (I do not expect these runtime
function to be called in hot loop nests).
Differential Revision: https://reviews.llvm.org/D123388
mlir::Value createConvert(mlir::Location loc, mlir::Type toTy,
mlir::Value val);
+ /// Create a fir.store of \p val into \p addr. A lazy conversion
+ /// of \p val to the element type of \p addr is created if needed.
+ void createStoreWithConvert(mlir::Location loc, mlir::Value val,
+ mlir::Value addr);
+
/// Create a new FuncOp. If the function may have already been created, use
/// `addNamedFunction` instead.
mlir::FuncOp createFunction(mlir::Location loc, llvm::StringRef name,
/// Generate call to COMMAND_ARGUMENT_COUNT intrinsic runtime routine.
mlir::Value genCommandArgumentCount(fir::FirOpBuilder &, mlir::Location);
-/// Generate call to GET_COMMAND_ARGUMENT intrinsic runtime routine.
-/// Note that GET_COMMAND_ARGUMENT intrinsic is split between 2 functions in
-/// implementation; ArgumentValue and ArgumentLength. So we handle each
-/// seperately.
-void genGetCommandArgument(fir::FirOpBuilder &, mlir::Location,
- mlir::Value number, mlir::Value value,
- mlir::Value length, mlir::Value status,
- mlir::Value errmsg);
-
-/// Generate call to GET_ENVIRONMENT_VARIABLE intrinsic runtime routine.
-/// Note that GET_ENVIRONMENT_ARGUMENT intrinsic is split between 2 functions in
-/// implementation; EnvVariableValue and EnvVariableLength. So we handle each
-/// seperately.
-void genGetEnvironmentVariable(fir::FirOpBuilder &, mlir::Location,
- mlir::Value number, mlir::Value value,
- mlir::Value length, mlir::Value status,
- mlir::Value trimName, mlir::Value errmsg);
+/// Generate a call to ArgumentValue runtime function which implements
+/// the part of GET_COMMAND_ARGUMENT related to VALUE, ERRMSG, and STATUS.
+/// \p value and \p errmsg must be fir.box that can be absent (but not null
+/// mlir values). The status value is returned.
+mlir::Value genArgumentValue(fir::FirOpBuilder &, mlir::Location,
+ mlir::Value number, mlir::Value value,
+ mlir::Value errmsg);
+
+/// Generate a call to ArgumentLength runtime function which implements
+/// the part of GET_COMMAND_ARGUMENT related to LENGTH.
+/// It returns the length of the \p number command arguments.
+mlir::Value genArgumentLength(fir::FirOpBuilder &, mlir::Location,
+ mlir::Value number);
+
+/// Generate a call to EnvVariableValue runtime function which implements
+/// the part of GET_ENVIRONMENT_ARGUMENT related to VALUE, ERRMSG, and STATUS.
+/// \p value and \p errmsg must be fir.box that can be absent (but not null
+/// mlir values). The status value is returned. \p name must be a fir.box.
+/// and \p trimName a boolean value.
+mlir::Value genEnvVariableValue(fir::FirOpBuilder &, mlir::Location,
+ mlir::Value name, mlir::Value value,
+ mlir::Value trimName, mlir::Value errmsg);
+
+/// Generate a call to EnvVariableLength runtime function which implements
+/// the part of GET_ENVIRONMENT_ARGUMENT related to LENGTH.
+/// It returns the length of the \p number command arguments.
+/// \p name must be a fir.box and \p trimName a boolean value.
+mlir::Value genEnvVariableLength(fir::FirOpBuilder &, mlir::Location,
+ mlir::Value name, mlir::Value trimName);
} // namespace fir::runtime
#endif // FORTRAN_OPTIMIZER_BUILDER_RUNTIME_COMMAND_H
{"get_command_argument",
&I::genGetCommandArgument,
{{{"number", asValue},
- {"value", asAddr},
+ {"value", asBox, handleDynamicOptional},
{"length", asAddr},
{"status", asAddr},
- {"errmsg", asAddr}}},
+ {"errmsg", asBox, handleDynamicOptional}}},
/*isElemental=*/false},
{"get_environment_variable",
&I::genGetEnvironmentVariable,
- {{{"name", asValue},
- {"value", asAddr},
+ {{{"name", asBox},
+ {"value", asBox, handleDynamicOptional},
{"length", asAddr},
{"status", asAddr},
- {"trim_name", asValue},
- {"errmsg", asAddr}}},
+ {"trim_name", asAddr},
+ {"errmsg", asBox, handleDynamicOptional}}},
/*isElemental=*/false},
{"iachar", &I::genIchar},
{"iand", &I::genIand},
void IntrinsicLibrary::genGetCommandArgument(
llvm::ArrayRef<fir::ExtendedValue> args) {
assert(args.size() == 5);
-
- auto processCharBox = [&](llvm::Optional<fir::CharBoxValue> arg,
- mlir::Value &value) -> void {
- if (arg.hasValue()) {
- value = builder.createBox(loc, *arg);
- } else {
- value = builder
- .create<fir::AbsentOp>(
- loc, fir::BoxType::get(builder.getNoneType()))
- .getResult();
- }
- };
-
- // Handle NUMBER argument
mlir::Value number = fir::getBase(args[0]);
+ const fir::ExtendedValue &value = args[1];
+ const fir::ExtendedValue &length = args[2];
+ const fir::ExtendedValue &status = args[3];
+ const fir::ExtendedValue &errmsg = args[4];
+
if (!number)
fir::emitFatalError(loc, "expected NUMBER parameter");
- // Handle optional VALUE argument
- mlir::Value value;
- llvm::Optional<fir::CharBoxValue> valBox;
- if (const fir::CharBoxValue *charBox = args[1].getCharBox())
- valBox = *charBox;
- processCharBox(valBox, value);
-
- // Handle optional LENGTH argument
- mlir::Value length = fir::getBase(args[2]);
-
- // Handle optional STATUS argument
- mlir::Value status = fir::getBase(args[3]);
-
- // Handle optional ERRMSG argument
- mlir::Value errmsg;
- llvm::Optional<fir::CharBoxValue> errmsgBox;
- if (const fir::CharBoxValue *charBox = args[4].getCharBox())
- errmsgBox = *charBox;
- processCharBox(errmsgBox, errmsg);
-
- fir::runtime::genGetCommandArgument(builder, loc, number, value, length,
- status, errmsg);
+ if (isStaticallyPresent(value) || isStaticallyPresent(status) ||
+ isStaticallyPresent(errmsg)) {
+ mlir::Type boxNoneTy = fir::BoxType::get(builder.getNoneType());
+ mlir::Value valBox =
+ isStaticallyPresent(value)
+ ? fir::getBase(value)
+ : builder.create<fir::AbsentOp>(loc, boxNoneTy).getResult();
+ mlir::Value errBox =
+ isStaticallyPresent(errmsg)
+ ? fir::getBase(errmsg)
+ : builder.create<fir::AbsentOp>(loc, boxNoneTy).getResult();
+ mlir::Value stat =
+ fir::runtime::genArgumentValue(builder, loc, number, valBox, errBox);
+ if (isStaticallyPresent(status)) {
+ mlir::Value statAddr = fir::getBase(status);
+ mlir::Value statIsPresentAtRuntime = builder.genIsNotNull(loc, statAddr);
+ builder.genIfThen(loc, statIsPresentAtRuntime)
+ .genThen(
+ [&]() { builder.createStoreWithConvert(loc, stat, statAddr); })
+ .end();
+ }
+ }
+ if (isStaticallyPresent(length)) {
+ mlir::Value lenAddr = fir::getBase(length);
+ mlir::Value lenIsPresentAtRuntime = builder.genIsNotNull(loc, lenAddr);
+ builder.genIfThen(loc, lenIsPresentAtRuntime)
+ .genThen([&]() {
+ mlir::Value len =
+ fir::runtime::genArgumentLength(builder, loc, number);
+ builder.createStoreWithConvert(loc, len, lenAddr);
+ })
+ .end();
+ }
}
// GET_ENVIRONMENT_VARIABLE
void IntrinsicLibrary::genGetEnvironmentVariable(
llvm::ArrayRef<fir::ExtendedValue> args) {
assert(args.size() == 6);
+ mlir::Value name = fir::getBase(args[0]);
+ const fir::ExtendedValue &value = args[1];
+ const fir::ExtendedValue &length = args[2];
+ const fir::ExtendedValue &status = args[3];
+ const fir::ExtendedValue &trimName = args[4];
+ const fir::ExtendedValue &errmsg = args[5];
- auto processCharBox = [&](llvm::Optional<fir::CharBoxValue> arg,
- mlir::Value &value) -> void {
- if (arg.hasValue()) {
- value = builder.createBox(loc, *arg);
- } else {
- value = builder
- .create<fir::AbsentOp>(
- loc, fir::BoxType::get(builder.getNoneType()))
- .getResult();
- }
- };
-
- // Handle NAME argument
- mlir::Value name;
- if (const fir::CharBoxValue *charBox = args[0].getCharBox()) {
- llvm::Optional<fir::CharBoxValue> nameBox = *charBox;
- assert(nameBox.hasValue());
- name = builder.createBox(loc, *nameBox);
+ // Handle optional TRIM_NAME argument
+ mlir::Value trim;
+ if (isStaticallyAbsent(trimName)) {
+ trim = builder.createBool(loc, true);
+ } else {
+ mlir::Type i1Ty = builder.getI1Type();
+ mlir::Value trimNameAddr = fir::getBase(trimName);
+ mlir::Value trimNameIsPresentAtRuntime =
+ builder.genIsNotNull(loc, trimNameAddr);
+ trim = builder
+ .genIfOp(loc, {i1Ty}, trimNameIsPresentAtRuntime,
+ /*withElseRegion=*/true)
+ .genThen([&]() {
+ auto trimLoad = builder.create<fir::LoadOp>(loc, trimNameAddr);
+ mlir::Value cast = builder.createConvert(loc, i1Ty, trimLoad);
+ builder.create<fir::ResultOp>(loc, cast);
+ })
+ .genElse([&]() {
+ mlir::Value trueVal = builder.createBool(loc, true);
+ builder.create<fir::ResultOp>(loc, trueVal);
+ })
+ .getResults()[0];
}
- // Handle optional VALUE argument
- mlir::Value value;
- llvm::Optional<fir::CharBoxValue> valBox;
- if (const fir::CharBoxValue *charBox = args[1].getCharBox())
- valBox = *charBox;
- processCharBox(valBox, value);
-
- // Handle optional LENGTH argument
- mlir::Value length = fir::getBase(args[2]);
-
- // Handle optional STATUS argument
- mlir::Value status = fir::getBase(args[3]);
+ if (isStaticallyPresent(value) || isStaticallyPresent(status) ||
+ isStaticallyPresent(errmsg)) {
+ mlir::Type boxNoneTy = fir::BoxType::get(builder.getNoneType());
+ mlir::Value valBox =
+ isStaticallyPresent(value)
+ ? fir::getBase(value)
+ : builder.create<fir::AbsentOp>(loc, boxNoneTy).getResult();
+ mlir::Value errBox =
+ isStaticallyPresent(errmsg)
+ ? fir::getBase(errmsg)
+ : builder.create<fir::AbsentOp>(loc, boxNoneTy).getResult();
+ mlir::Value stat = fir::runtime::genEnvVariableValue(builder, loc, name,
+ valBox, trim, errBox);
+ if (isStaticallyPresent(status)) {
+ mlir::Value statAddr = fir::getBase(status);
+ mlir::Value statIsPresentAtRuntime = builder.genIsNotNull(loc, statAddr);
+ builder.genIfThen(loc, statIsPresentAtRuntime)
+ .genThen(
+ [&]() { builder.createStoreWithConvert(loc, stat, statAddr); })
+ .end();
+ }
+ }
- // Handle optional TRIM_NAME argument
- mlir::Value trim_name = isStaticallyAbsent(args[4])
- ? builder.createBool(loc, true)
- : fir::getBase(args[4]);
-
- // Handle optional ERRMSG argument
- mlir::Value errmsg;
- llvm::Optional<fir::CharBoxValue> errmsgBox;
- if (const fir::CharBoxValue *charBox = args[5].getCharBox())
- errmsgBox = *charBox;
- processCharBox(errmsgBox, errmsg);
-
- fir::runtime::genGetEnvironmentVariable(builder, loc, name, value, length,
- status, trim_name, errmsg);
+ if (isStaticallyPresent(length)) {
+ mlir::Value lenAddr = fir::getBase(length);
+ mlir::Value lenIsPresentAtRuntime = builder.genIsNotNull(loc, lenAddr);
+ builder.genIfThen(loc, lenIsPresentAtRuntime)
+ .genThen([&]() {
+ mlir::Value len =
+ fir::runtime::genEnvVariableLength(builder, loc, name, trim);
+ builder.createStoreWithConvert(loc, len, lenAddr);
+ })
+ .end();
+ }
}
// IAND
return val;
}
+void fir::FirOpBuilder::createStoreWithConvert(mlir::Location loc,
+ mlir::Value val,
+ mlir::Value addr) {
+ mlir::Value cast =
+ createConvert(loc, fir::unwrapRefType(addr.getType()), val);
+ create<fir::StoreOp>(loc, cast, addr);
+}
+
fir::StringLitOp fir::FirOpBuilder::createStringLitOp(mlir::Location loc,
llvm::StringRef data) {
auto type = fir::CharacterType::get(getContext(), 1, data.size());
return builder.create<fir::CallOp>(loc, argumentCountFunc).getResult(0);
}
-void fir::runtime::genGetCommandArgument(fir::FirOpBuilder &builder,
- mlir::Location loc, mlir::Value number,
- mlir::Value value, mlir::Value length,
- mlir::Value status,
- mlir::Value errmsg) {
+mlir::Value fir::runtime::genArgumentValue(fir::FirOpBuilder &builder,
+ mlir::Location loc,
+ mlir::Value number,
+ mlir::Value value,
+ mlir::Value errmsg) {
auto argumentValueFunc =
fir::runtime::getRuntimeFunc<mkRTKey(ArgumentValue)>(loc, builder);
+ llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
+ builder, loc, argumentValueFunc.getFunctionType(), number, value, errmsg);
+ return builder.create<fir::CallOp>(loc, argumentValueFunc, args).getResult(0);
+}
+
+mlir::Value fir::runtime::genArgumentLength(fir::FirOpBuilder &builder,
+ mlir::Location loc,
+ mlir::Value number) {
auto argumentLengthFunc =
fir::runtime::getRuntimeFunc<mkRTKey(ArgumentLength)>(loc, builder);
-
- mlir::Value valueResult;
- // Run `ArgumentValue` intrinsic only if we have a "value" in either "VALUE",
- // "STATUS" or "ERRMSG" parameters.
- if (!isAbsent(value) || status || !isAbsent(errmsg)) {
- llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
- builder, loc, argumentValueFunc.getFunctionType(), number, value,
- errmsg);
- valueResult =
- builder.create<fir::CallOp>(loc, argumentValueFunc, args).getResult(0);
- }
-
- // Only save result of `ArgumentValue` if "STATUS" parameter has been given
- if (status) {
- const mlir::Value statusLoaded = builder.create<fir::LoadOp>(loc, status);
- mlir::Value resultCast =
- builder.createConvert(loc, statusLoaded.getType(), valueResult);
- builder.create<fir::StoreOp>(loc, resultCast, status);
- }
-
- // Only run `ArgumentLength` intrinsic if "LENGTH" parameter provided
- if (length) {
- llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
- builder, loc, argumentLengthFunc.getFunctionType(), number);
- mlir::Value result =
- builder.create<fir::CallOp>(loc, argumentLengthFunc, args).getResult(0);
- const mlir::Value valueLoaded = builder.create<fir::LoadOp>(loc, length);
- mlir::Value resultCast =
- builder.createConvert(loc, valueLoaded.getType(), result);
- builder.create<fir::StoreOp>(loc, resultCast, length);
- }
+ llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
+ builder, loc, argumentLengthFunc.getFunctionType(), number);
+ return builder.create<fir::CallOp>(loc, argumentLengthFunc, args)
+ .getResult(0);
}
-void fir::runtime::genGetEnvironmentVariable(
+mlir::Value fir::runtime::genEnvVariableValue(
fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value name,
- mlir::Value value, mlir::Value length, mlir::Value status,
- mlir::Value trimName, mlir::Value errmsg) {
+ mlir::Value value, mlir::Value trimName, mlir::Value errmsg) {
auto valueFunc =
fir::runtime::getRuntimeFunc<mkRTKey(EnvVariableValue)>(loc, builder);
+ mlir::FunctionType valueFuncTy = valueFunc.getFunctionType();
+ mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc);
+ mlir::Value sourceLine =
+ fir::factory::locationToLineNo(builder, loc, valueFuncTy.getInput(5));
+ llvm::SmallVector<mlir::Value> args =
+ fir::runtime::createArguments(builder, loc, valueFuncTy, name, value,
+ trimName, errmsg, sourceFile, sourceLine);
+ return builder.create<fir::CallOp>(loc, valueFunc, args).getResult(0);
+}
+
+mlir::Value fir::runtime::genEnvVariableLength(fir::FirOpBuilder &builder,
+ mlir::Location loc,
+ mlir::Value name,
+ mlir::Value trimName) {
auto lengthFunc =
fir::runtime::getRuntimeFunc<mkRTKey(EnvVariableLength)>(loc, builder);
-
- mlir::Value sourceFile;
- mlir::Value sourceLine;
- // We only need `sourceFile` and `sourceLine` variables when calling either
- // `EnvVariableValue` or `EnvVariableLength` below.
- if (!isAbsent(value) || status || !isAbsent(errmsg) || length) {
- sourceFile = fir::factory::locationToFilename(builder, loc);
- sourceLine = fir::factory::locationToLineNo(
- builder, loc, valueFunc.getFunctionType().getInput(5));
- }
-
- mlir::Value valueResult;
- // Run `EnvVariableValue` intrinsic only if we have a "value" in either
- // "VALUE", "STATUS" or "ERRMSG" parameters.
- if (!isAbsent(value) || status || !isAbsent(errmsg)) {
- llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
- builder, loc, valueFunc.getFunctionType(), name, value, trimName,
- errmsg, sourceFile, sourceLine);
- valueResult =
- builder.create<fir::CallOp>(loc, valueFunc, args).getResult(0);
- }
-
- // Only save result of `EnvVariableValue` if "STATUS" parameter provided
- if (status) {
- const mlir::Value statusLoaded = builder.create<fir::LoadOp>(loc, status);
- mlir::Value resultCast =
- builder.createConvert(loc, statusLoaded.getType(), valueResult);
- builder.create<fir::StoreOp>(loc, resultCast, status);
- }
-
- // Only run `EnvVariableLength` intrinsic if "LENGTH" parameter provided
- if (length) {
- llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
- builder, loc, lengthFunc.getFunctionType(), name, trimName, sourceFile,
- sourceLine);
- mlir::Value result =
- builder.create<fir::CallOp>(loc, lengthFunc, args).getResult(0);
- const mlir::Value lengthLoaded = builder.create<fir::LoadOp>(loc, length);
- mlir::Value resultCast =
- builder.createConvert(loc, lengthLoaded.getType(), result);
- builder.create<fir::StoreOp>(loc, resultCast, length);
- }
+ mlir::FunctionType lengthFuncTy = lengthFunc.getFunctionType();
+ mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc);
+ mlir::Value sourceLine =
+ fir::factory::locationToLineNo(builder, loc, lengthFuncTy.getInput(3));
+ llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
+ builder, loc, lengthFuncTy, name, trimName, sourceFile, sourceLine);
+ return builder.create<fir::CallOp>(loc, lengthFunc, args).getResult(0);
}
--- /dev/null
+! Test GET_COMMAND_ARGUMENT with dynamically optional arguments.
+! RUN: bbc -emit-fir %s -o - | FileCheck %s
+
+! CHECK-LABEL: func @_QPtest(
+! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "number", fir.optional},
+! CHECK-SAME: %[[VAL_1:.*]]: !fir.boxchar<1> {fir.bindc_name = "value", fir.optional},
+! CHECK-SAME: %[[VAL_2:.*]]: !fir.ref<i32> {fir.bindc_name = "length", fir.optional},
+! CHECK-SAME: %[[VAL_3:.*]]: !fir.ref<i32> {fir.bindc_name = "status", fir.optional},
+! CHECK-SAME: %[[VAL_4:.*]]: !fir.boxchar<1> {fir.bindc_name = "errmsg", fir.optional}) {
+subroutine test(number, value, length, status, errmsg)
+ integer, optional :: number, status, length
+ character(*), optional :: value, errmsg
+ ! Note: number cannot be absent
+ call get_command_argument(number, value, length, status, errmsg)
+! CHECK: %[[VAL_5:.*]]:2 = fir.unboxchar %[[VAL_4]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
+! CHECK: %[[VAL_6:.*]]:2 = fir.unboxchar %[[VAL_1]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
+! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_0]] : !fir.ref<i32>
+! CHECK: %[[VAL_8:.*]] = fir.is_present %[[VAL_6]]#0 : (!fir.ref<!fir.char<1,?>>) -> i1
+! CHECK: %[[VAL_9:.*]] = fir.embox %[[VAL_6]]#0 typeparams %[[VAL_6]]#1 : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>>
+! CHECK: %[[VAL_10:.*]] = fir.absent !fir.box<!fir.char<1,?>>
+! CHECK: %[[VAL_11:.*]] = arith.select %[[VAL_8]], %[[VAL_9]], %[[VAL_10]] : !fir.box<!fir.char<1,?>>
+! CHECK: %[[VAL_12:.*]] = fir.is_present %[[VAL_5]]#0 : (!fir.ref<!fir.char<1,?>>) -> i1
+! CHECK: %[[VAL_13:.*]] = fir.embox %[[VAL_5]]#0 typeparams %[[VAL_5]]#1 : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>>
+! CHECK: %[[VAL_14:.*]] = fir.absent !fir.box<!fir.char<1,?>>
+! CHECK: %[[VAL_15:.*]] = arith.select %[[VAL_12]], %[[VAL_13]], %[[VAL_14]] : !fir.box<!fir.char<1,?>>
+! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_11]] : (!fir.box<!fir.char<1,?>>) -> !fir.box<none>
+! CHECK: %[[VAL_17:.*]] = fir.convert %[[VAL_15]] : (!fir.box<!fir.char<1,?>>) -> !fir.box<none>
+! CHECK: %[[VAL_18:.*]] = fir.call @_FortranAArgumentValue(%[[VAL_7]], %[[VAL_16]], %[[VAL_17]]) : (i32, !fir.box<none>, !fir.box<none>) -> i32
+! CHECK: %[[VAL_19:.*]] = fir.convert %[[VAL_3]] : (!fir.ref<i32>) -> i64
+! CHECK: %[[VAL_20:.*]] = arith.constant 0 : i64
+! CHECK: %[[VAL_21:.*]] = arith.cmpi ne, %[[VAL_19]], %[[VAL_20]] : i64
+! CHECK: fir.if %[[VAL_21]] {
+! CHECK: fir.store %[[VAL_18]] to %[[VAL_3]] : !fir.ref<i32>
+! CHECK: }
+! CHECK: %[[VAL_22:.*]] = fir.convert %[[VAL_2]] : (!fir.ref<i32>) -> i64
+! CHECK: %[[VAL_23:.*]] = arith.constant 0 : i64
+! CHECK: %[[VAL_24:.*]] = arith.cmpi ne, %[[VAL_22]], %[[VAL_23]] : i64
+! CHECK: fir.if %[[VAL_24]] {
+! CHECK: %[[VAL_25:.*]] = fir.call @_FortranAArgumentLength(%[[VAL_7]]) : (i32) -> i64
+! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_25]] : (i64) -> i32
+! CHECK: fir.store %[[VAL_26]] to %[[VAL_2]] : !fir.ref<i32>
+! CHECK: }
+end subroutine
! CHECK-NEXT: %[[errmsgBuffer:.*]] = fir.convert %[[errmsgBoxed]] : (!fir.box<!fir.char<1,?>>) -> !fir.box<none>
! CHECK-32-NEXT: %[[statusResult:.*]] = fir.call @_FortranAArgumentValue(%[[numUnboxed]], %[[valueBuffer]], %[[errmsgBuffer]]) : (i32, !fir.box<none>, !fir.box<none>) -> i32
! CHECK-64-NEXT: %[[statusResult32:.*]] = fir.call @_FortranAArgumentValue(%[[numCast]], %[[valueBuffer]], %[[errmsgBuffer]]) : (i32, !fir.box<none>, !fir.box<none>) -> i32
-! CHECK-64-NEXT: %[[statusResult:.*]] = fir.convert %[[statusResult32]] : (i32) -> i64
-! CHECK-NEXT: fir.store %[[statusResult]] to %[[status]] : !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>
-! CHECK-64-NEXT: %[[numCast:.*]] = fir.convert %[[numUnboxed]] : (i64) -> i32
-! CHECK-32-NEXT: %[[lengthResult64:.*]] = fir.call @_FortranAArgumentLength(%[[numUnboxed]]) : (i32) -> i64
-! CHECK-64-NEXT: %[[lengthResult:.*]] = fir.call @_FortranAArgumentLength(%[[numCast]]) : (i32) -> i64
+! CHECK-64: %[[statusResult:.*]] = fir.convert %[[statusResult32]] : (i32) -> i64
+! CHECK: fir.store %[[statusResult]] to %[[status]] : !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>
+! CHECK-64: %[[numCast:.*]] = fir.convert %[[numUnboxed]] : (i64) -> i32
+! CHECK-32: %[[lengthResult64:.*]] = fir.call @_FortranAArgumentLength(%[[numUnboxed]]) : (i32) -> i64
+! CHECK-64: %[[lengthResult:.*]] = fir.call @_FortranAArgumentLength(%[[numCast]]) : (i32) -> i64
! CHECK-32-NEXT: %[[lengthResult:.*]] = fir.convert %[[lengthResult64]] : (i64) -> i32
! CHECK-NEXT: fir.store %[[lengthResult]] to %[[length]] : !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>
end subroutine all_arguments
call get_command_argument(num, LENGTH=length)
! CHECK-NOT: fir.call @_FortranAArgumentValue
! CHECK: %[[numLoaded:.*]] = fir.load %[[num]] : !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>
-! CHECK-64-NEXT: %[[numCast:.*]] = fir.convert %[[numLoaded]] : (i64) -> i32
-! CHECK-32-NEXT: %[[result64:.*]] = fir.call @_FortranAArgumentLength(%[[numLoaded]]) : (i32) -> i64
-! CHECK-64-NEXT: %[[result:.*]] = fir.call @_FortranAArgumentLength(%[[numCast]]) : (i32) -> i64
+! CHECK-64: %[[numCast:.*]] = fir.convert %[[numLoaded]] : (i64) -> i32
+! CHECK-32: %[[result64:.*]] = fir.call @_FortranAArgumentLength(%[[numLoaded]]) : (i32) -> i64
+! CHECK-64: %[[result:.*]] = fir.call @_FortranAArgumentLength(%[[numCast]]) : (i32) -> i64
! CHECK-32-NEXT: %[[result:.*]] = fir.convert %[[result64]] : (i64) -> i32
! CHECK-NEXT: fir.store %[[result]] to %[[length]] : !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>
-! CHECK-NEXT: return
end subroutine number_and_length_only
! CHECK-LABEL: func @_QPnumber_and_status_only(
! CHECK: %[[numLoaded:.*]] = fir.load %[[num]] : !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>
! CHECK-NEXT: %[[value:.*]] = fir.absent !fir.box<none>
! CHECK-NEXT: %[[errmsg:.*]] = fir.absent !fir.box<none>
-! CHECK-64-NEXT: %[[numCast:.*]] = fir.convert %[[numLoaded]] : (i64) -> i32
+! CHECK-64: %[[numCast:.*]] = fir.convert %[[numLoaded]] : (i64) -> i32
! CHECK-32-NEXT: %[[result:.*]] = fir.call @_FortranAArgumentValue(%[[numLoaded]], %[[value]], %[[errmsg]]) : (i32, !fir.box<none>, !fir.box<none>) -> i32
! CHECK-64-NEXT: %[[result32:.*]] = fir.call @_FortranAArgumentValue(%[[numCast]], %[[value]], %[[errmsg]]) : (i32, !fir.box<none>, !fir.box<none>) -> i32
-! CHECK-64-NEXT: %[[result:.*]] = fir.convert %[[result32]] : (i32) -> i64
-! CHECK-32-NEXT: fir.store %[[result]] to %[[status]] : !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>
+! CHECK-64: %[[result:.*]] = fir.convert %[[result32]] : (i32) -> i64
+! CHECK-32: fir.store %[[result]] to %[[status]] : !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>
! CHECK-NOT: fir.call @_FortranAArgumentLength
end subroutine number_and_status_only
! CHECK: %[[errmsgUnboxed:.*]]:2 = fir.unboxchar %[[errmsg]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
! CHECK-NEXT: %[[errmsgLength:.*]] = arith.constant 32 : index
! CHECK-NEXT: %[[numUnboxed:.*]] = fir.load %[[num]] : !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>
-! CHECK-NEXT: %[[value:.*]] = fir.absent !fir.box<none>
! CHECK-NEXT: %[[errmsgBoxed:.*]] = fir.embox %[[errmsgUnboxed]]#0 typeparams %[[errmsgLength]] : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>>
-! CHECK-64-NEXT: %[[numCast:.*]] = fir.convert %[[numUnboxed]] : (i64) -> i32
+! CHECK-NEXT: %[[value:.*]] = fir.absent !fir.box<none>
+! CHECK-64: %[[numCast:.*]] = fir.convert %[[numUnboxed]] : (i64) -> i32
! CHECK-NEXT: %[[errmsg:.*]] = fir.convert %[[errmsgBoxed]] : (!fir.box<!fir.char<1,?>>) -> !fir.box<none>
! CHECK-32-NEXT: %{{[0-9]+}} = fir.call @_FortranAArgumentValue(%[[numUnboxed]], %[[value]], %[[errmsg]]) : (i32, !fir.box<none>, !fir.box<none>) -> i32
! CHECK-64-NEXT: %{{[0-9]+}} = fir.call @_FortranAArgumentValue(%[[numCast]], %[[value]], %[[errmsg]]) : (i32, !fir.box<none>, !fir.box<none>) -> i32
--- /dev/null
+! Test GET_ENVIRONMENT_VARIABLE with dynamically optional arguments.
+! RUN: bbc -emit-fir %s -o - | FileCheck %s
+
+
+! CHECK-LABEL: func @_QPtest(
+! CHECK-SAME: %[[VAL_0:.*]]: !fir.boxchar<1> {fir.bindc_name = "name", fir.optional},
+! CHECK-SAME: %[[VAL_1:.*]]: !fir.boxchar<1> {fir.bindc_name = "value", fir.optional},
+! CHECK-SAME: %[[VAL_2:.*]]: !fir.ref<i32> {fir.bindc_name = "length", fir.optional},
+! CHECK-SAME: %[[VAL_3:.*]]: !fir.ref<i32> {fir.bindc_name = "status", fir.optional},
+! CHECK-SAME: %[[VAL_4:.*]]: !fir.ref<!fir.logical<4>> {fir.bindc_name = "trim_name", fir.optional},
+! CHECK-SAME: %[[VAL_5:.*]]: !fir.boxchar<1> {fir.bindc_name = "errmsg", fir.optional}) {
+subroutine test(name, value, length, status, trim_name, errmsg)
+ integer, optional :: status, length
+ character(*), optional :: name, value, errmsg
+ logical, optional :: trim_name
+ ! Note: name is not optional in et_environment_variable and must be present
+ call get_environment_variable(name, value, length, status, trim_name, errmsg)
+! CHECK: %[[VAL_6:.*]]:2 = fir.unboxchar %[[VAL_5]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
+! CHECK: %[[VAL_7:.*]]:2 = fir.unboxchar %[[VAL_0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
+! CHECK: %[[VAL_8:.*]]:2 = fir.unboxchar %[[VAL_1]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
+! CHECK: %[[VAL_9:.*]] = fir.embox %[[VAL_7]]#0 typeparams %[[VAL_7]]#1 : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>>
+! CHECK: %[[VAL_10:.*]] = fir.is_present %[[VAL_8]]#0 : (!fir.ref<!fir.char<1,?>>) -> i1
+! CHECK: %[[VAL_11:.*]] = fir.embox %[[VAL_8]]#0 typeparams %[[VAL_8]]#1 : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>>
+! CHECK: %[[VAL_12:.*]] = fir.absent !fir.box<!fir.char<1,?>>
+! CHECK: %[[VAL_13:.*]] = arith.select %[[VAL_10]], %[[VAL_11]], %[[VAL_12]] : !fir.box<!fir.char<1,?>>
+! CHECK: %[[VAL_14:.*]] = fir.is_present %[[VAL_6]]#0 : (!fir.ref<!fir.char<1,?>>) -> i1
+! CHECK: %[[VAL_15:.*]] = fir.embox %[[VAL_6]]#0 typeparams %[[VAL_6]]#1 : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>>
+! CHECK: %[[VAL_16:.*]] = fir.absent !fir.box<!fir.char<1,?>>
+! CHECK: %[[VAL_17:.*]] = arith.select %[[VAL_14]], %[[VAL_15]], %[[VAL_16]] : !fir.box<!fir.char<1,?>>
+! CHECK: %[[VAL_18:.*]] = fir.convert %[[VAL_4]] : (!fir.ref<!fir.logical<4>>) -> i64
+! CHECK: %[[VAL_19:.*]] = arith.constant 0 : i64
+! CHECK: %[[VAL_20:.*]] = arith.cmpi ne, %[[VAL_18]], %[[VAL_19]] : i64
+! CHECK: %[[VAL_21:.*]] = fir.if %[[VAL_20]] -> (i1) {
+! CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_4]] : !fir.ref<!fir.logical<4>>
+! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_22]] : (!fir.logical<4>) -> i1
+! CHECK: fir.result %[[VAL_23]] : i1
+! CHECK: } else {
+! CHECK: %[[VAL_24:.*]] = arith.constant true
+! CHECK: fir.result %[[VAL_24]] : i1
+! CHECK: }
+! CHECK: %[[VAL_27:.*]] = fir.convert %[[VAL_9]] : (!fir.box<!fir.char<1,?>>) -> !fir.box<none>
+! CHECK: %[[VAL_28:.*]] = fir.convert %[[VAL_13]] : (!fir.box<!fir.char<1,?>>) -> !fir.box<none>
+! CHECK: %[[VAL_29:.*]] = fir.convert %[[VAL_17]] : (!fir.box<!fir.char<1,?>>) -> !fir.box<none>
+! CHECK: %[[VAL_31:.*]] = fir.call @_FortranAEnvVariableValue(%[[VAL_27]], %[[VAL_28]], %[[VAL_32:.*]], %[[VAL_29]], %{{.*}}, %{{.*}}) : (!fir.box<none>, !fir.box<none>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
+! CHECK: %[[VAL_33:.*]] = fir.convert %[[VAL_3]] : (!fir.ref<i32>) -> i64
+! CHECK: %[[VAL_34:.*]] = arith.constant 0 : i64
+! CHECK: %[[VAL_35:.*]] = arith.cmpi ne, %[[VAL_33]], %[[VAL_34]] : i64
+! CHECK: fir.if %[[VAL_35]] {
+! CHECK: fir.store %[[VAL_31]] to %[[VAL_3]] : !fir.ref<i32>
+! CHECK: }
+! CHECK: %[[VAL_36:.*]] = fir.convert %[[VAL_2]] : (!fir.ref<i32>) -> i64
+! CHECK: %[[VAL_37:.*]] = arith.constant 0 : i64
+! CHECK: %[[VAL_38:.*]] = arith.cmpi ne, %[[VAL_36]], %[[VAL_37]] : i64
+! CHECK: fir.if %[[VAL_38]] {
+! CHECK: %[[VAL_41:.*]] = fir.convert %[[VAL_9]] : (!fir.box<!fir.char<1,?>>) -> !fir.box<none>
+! CHECK: %[[VAL_43:.*]] = fir.call @_FortranAEnvVariableLength(%[[VAL_41]], %[[VAL_32]], %{{.*}}, %{{.*}}) : (!fir.box<none>, i1, !fir.ref<i8>, i32) -> i64
+! CHECK: %[[VAL_44:.*]] = fir.convert %[[VAL_43]] : (i64) -> i32
+! CHECK: fir.store %[[VAL_44]] to %[[VAL_2]] : !fir.ref<i32>
+! CHECK: }
+end subroutine
! CHECK-NEXT: %[[nameLength:.*]] = arith.constant 32 : index
! CHECK-NEXT: %[[nameBox:.*]] = fir.embox %0#0 typeparams %[[nameLength]] : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>>
! CHECK-NEXT: %true = arith.constant true
-! CHECK-NEXT: %[[sourceFileString:.*]] = fir.address_of(@_QQcl.{{.*}}) : !fir.ref<!fir.char<1,[[sourceFileLength:.*]]>>
+! CHECK: %[[sourceFileString:.*]] = fir.address_of(@_QQcl.{{.*}}) : !fir.ref<!fir.char<1,[[sourceFileLength:.*]]>>
! CHECK-NEXT: %[[sourceLine:.*]] = arith.constant [[# @LINE - 7]] : i32
! CHECK-NEXT: %[[name:.*]] = fir.convert %[[nameBox]] : (!fir.box<!fir.char<1,?>>) -> !fir.box<none>
! CHECK-NEXT: %[[sourceFile:.*]] = fir.convert %[[sourceFileString]] : (!fir.ref<!fir.char<1,[[sourceFileLength]]>>) -> !fir.ref<i8>
! CHECK-64-NEXT: %[[length:.*]] = fir.call @_FortranAEnvVariableLength(%[[name]], %true, %[[sourceFile]], %[[sourceLine]]) : (!fir.box<none>, i1, !fir.ref<i8>, i32) -> i64
! CHECK-32-NEXT: %[[length:.*]] = fir.convert %[[length64]] : (i64) -> i32
! CHECK-NEXT: fir.store %[[length]] to %[[lengthArg]] : !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>
-! CHECK-NEXT: return
end subroutine name_and_length_only
! CHECK-LABEL: func @_QPname_and_status_only(
! CHECK: %[[nameUnbox:.*]]:2 = fir.unboxchar %[[nameArg]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
! CHECK-NEXT: %[[nameLength:.*]] = arith.constant 32 : index
! CHECK-NEXT: %[[nameBox:.*]] = fir.embox %[[nameUnbox]]#0 typeparams %[[nameLength]] : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>>
-! CHECK-NEXT: %[[value:.*]] = fir.absent !fir.box<none>
! CHECK-NEXT: %true = arith.constant true
+! CHECK-NEXT: %[[value:.*]] = fir.absent !fir.box<none>
! CHECK-NEXT: %[[errmsg:.*]] = fir.absent !fir.box<none>
! CHECK-NEXT: %[[sourceFileString:.*]] = fir.address_of(@_QQcl.{{.*}}) : !fir.ref<!fir.char<1,[[sourceFileLength:.*]]>>
! CHECK-NEXT: %[[sourceLine:.*]] = arith.constant [[# @LINE - 8]] : i32
! CHECK-NEXT: %[[sourceFile:.*]] = fir.convert %[[sourceFileString]] : (!fir.ref<!fir.char<1,[[sourceFileLength]]>>) -> !fir.ref<i8>
! CHECK-32-NEXT: %[[status:.*]] = fir.call @_FortranAEnvVariableValue(%[[name]], %[[value]], %true, %[[errmsg]], %[[sourceFile]], %[[sourceLine]]) : (!fir.box<none>, !fir.box<none>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
! CHECK-64-NEXT: %[[status32:.*]] = fir.call @_FortranAEnvVariableValue(%[[name]], %[[value]], %true, %[[errmsg]], %[[sourceFile]], %[[sourceLine]]) : (!fir.box<none>, !fir.box<none>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
-! CHECK-64-NEXT: %[[status:.*]] = fir.convert %[[status32]] : (i32) -> i64
-! CHECK-NEXT: fir.store %[[status]] to %[[statusArg]] : !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>
-! CHECK-NEXT: return
+! CHECK-64: %[[status:.*]] = fir.convert %[[status32]] : (i32) -> i64
+! CHECK: fir.store %[[status]] to %[[statusArg]] : !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>
end subroutine name_and_status_only
! CHECK-LABEL: func @_QPname_and_trim_name_only(
! CHECK-NEXT: %[[nameUnbox:.*]]:2 = fir.unboxchar %[[nameArg]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
! CHECK-NEXT: %[[nameLength:.*]] = arith.constant 32 : index
! CHECK-NEXT: %[[nameBox:.*]] = fir.embox %[[nameUnbox]]#0 typeparams %[[nameLength]] : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>>
-! CHECK-NEXT: %[[value:.*]] = fir.absent !fir.box<none>
-! CHECK-NEXT: %true = arith.constant true
! CHECK-NEXT: %[[errmsgBox:.*]] = fir.embox %[[errmsgUnbox]]#0 typeparams %c32 : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>>
+! CHECK-NEXT: %true = arith.constant true
+! CHECK-NEXT: %[[value:.*]] = fir.absent !fir.box<none>
! CHECK-NEXT: %[[sourceFileString:.*]] = fir.address_of(@_QQcl.{{.*}}) : !fir.ref<!fir.char<1,[[sourceFileLength:.*]]>>
! CHECK-NEXT: %[[sourceLine:.*]] = arith.constant [[# @LINE - 10]] : i32
! CHECK-NEXT: %[[name:.*]] = fir.convert %[[nameBox]] : (!fir.box<!fir.char<1,?>>) -> !fir.box<none>
! CHECK-NEXT: %[[nameLength:.*]] = arith.constant 32 : index
! CHECK-NEXT: %[[valueUnbox:.*]]:2 = fir.unboxchar %[[valueArg]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
! CHECK-NEXT: %[[valueLength:.*]] = arith.constant 32 : index
-! CHECK-NEXT: %[[trimNameLoaded:.*]] = fir.load %[[trimNameArg]] : !fir.ref<!fir.logical<4>>
! CHECK-NEXT: %[[nameBoxed:.*]] = fir.embox %[[nameUnbox]]#0 typeparams %[[nameLength]] : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>>
! CHECK-NEXT: %[[valueBoxed:.*]] = fir.embox %[[valueUnbox]]#0 typeparams %[[valueLength]] : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>>
! CHECK-NEXT: %[[errmsgBoxed:.*]] = fir.embox %[[errmsgUnbox]]#0 typeparams %[[errmsgLength]] : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>>
-! CHECK-NEXT: %[[sourceFileString:.*]] = fir.address_of(@_QQcl.[[fileString:.*]]) : !fir.ref<!fir.char<1,[[fileStringLength:.*]]>>
-! CHECK-NEXT: %[[sourceLine:.*]] = arith.constant [[# @LINE - 12]] : i32
+! CHECK: %[[trimName:.*]] = fir.if %{{.*}} -> (i1) {
+! CHECK-NEXT: %[[trimNameLoaded:.*]] = fir.load %[[trimNameArg]] : !fir.ref<!fir.logical<4>>
+! CHECK-NEXT: %[[trimCast:.*]] = fir.convert %[[trimNameLoaded]] : (!fir.logical<4>) -> i1
+! CHECK-NEXT: fir.result %[[trimCast]] : i1
+! CHECK-NEXT: } else {
+! CHECK-NEXT: %[[trueVal:.*]] = arith.constant true
+! CHECK-NEXT: fir.result %[[trueVal]] : i1
+! CHECK-NEXT: }
+! CHECK: %[[sourceFileString:.*]] = fir.address_of(@_QQcl.[[fileString:.*]]) : !fir.ref<!fir.char<1,[[fileStringLength:.*]]>>
+! CHECK-NEXT: %[[sourceLine:.*]] = arith.constant [[# @LINE - 19]] : i32
! CHECK-NEXT: %[[name:.*]] = fir.convert %[[nameBoxed]] : (!fir.box<!fir.char<1,?>>) -> !fir.box<none>
! CHECK-NEXT: %[[value:.*]] = fir.convert %[[valueBoxed]] : (!fir.box<!fir.char<1,?>>) -> !fir.box<none>
-! CHECK-NEXT: %[[trimName:.*]] = fir.convert %[[trimNameLoaded]] : (!fir.logical<4>) -> i1
! CHECK-NEXT: %[[errmsg:.*]] = fir.convert %[[errmsgBoxed]] : (!fir.box<!fir.char<1,?>>) -> !fir.box<none>
! CHECK-NEXT: %[[sourceFile:.*]] = fir.convert %[[sourceFileString]] : (!fir.ref<!fir.char<1,[[fileStringLength]]>>) -> !fir.ref<i8>
! CHECK-32-NEXT: %[[status:.*]] = fir.call @_FortranAEnvVariableValue(%[[name]], %[[value]], %[[trimName]], %[[errmsg]], %[[sourceFile]], %[[sourceLine]]) : (!fir.box<none>, !fir.box<none>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
! CHECK-64-NEXT: %[[status32:.*]] = fir.call @_FortranAEnvVariableValue(%[[name]], %[[value]], %[[trimName]], %[[errmsg]], %[[sourceFile]], %[[sourceLine]]) : (!fir.box<none>, !fir.box<none>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
-! CHECK-64-NEXT: %[[status:.*]] = fir.convert %[[status32]] : (i32) -> i64
-! CHECK-NEXT: fir.store %[[status]] to %[[statusArg]] : !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>
+! CHECK-64: %[[status:.*]] = fir.convert %[[status32]] : (i32) -> i64
+! CHECK: fir.store %[[status]] to %[[statusArg]] : !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>
+! CHECK: %[[sourceFileString2:.*]] = fir.address_of(@_QQcl.[[fileString]]) : !fir.ref<!fir.char<1,[[fileStringLength]]>>
+! CHECK-NEXT: %[[sourceLine2:.*]] = arith.constant [[# @LINE - 29]] : i32
! CHECK-NEXT: %[[name:.*]] = fir.convert %[[nameBoxed]] : (!fir.box<!fir.char<1,?>>) -> !fir.box<none>
-! CHECK-NEXT: %[[trimName:.*]] = fir.convert %[[trimNameLoaded]] : (!fir.logical<4>) -> i1
-! CHECK-NEXT: %[[sourceFile:.*]] = fir.convert %[[sourceFileString]] : (!fir.ref<!fir.char<1,[[fileStringLength]]>>) -> !fir.ref<i8>
-! CHECK-32-NEXT: %[[result64:.*]] = fir.call @_FortranAEnvVariableLength(%[[name]], %[[trimName]], %[[sourceFile]], %[[sourceLine]]) : (!fir.box<none>, i1, !fir.ref<i8>, i32) -> i64
-! CHECK-64-NEXT: %[[result:.*]] = fir.call @_FortranAEnvVariableLength(%[[name]], %[[trimName]], %[[sourceFile]], %[[sourceLine]]) : (!fir.box<none>, i1, !fir.ref<i8>, i32) -> i64
-! CHECK-32-NEXT: %[[result:.*]] = fir.convert %[[result64]] : (i64) -> i32
+! CHECK-NEXT: %[[sourceFile2:.*]] = fir.convert %[[sourceFileString2]] : (!fir.ref<!fir.char<1,[[fileStringLength]]>>) -> !fir.ref<i8>
+! CHECK-32-NEXT: %[[result64:.*]] = fir.call @_FortranAEnvVariableLength(%[[name]], %[[trimName]], %[[sourceFile2]], %[[sourceLine2]]) : (!fir.box<none>, i1, !fir.ref<i8>, i32) -> i64
+! CHECK-64-NEXT: %[[result:.*]] = fir.call @_FortranAEnvVariableLength(%[[name]], %[[trimName]], %[[sourceFile2]], %[[sourceLine2]]) : (!fir.box<none>, i1, !fir.ref<i8>, i32) -> i64
+! CHECK-32: %[[result:.*]] = fir.convert %[[result64]] : (i64) -> i32
! CHECK-NEXT: fir.store %[[result]] to %[[lengthArg]] : !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>
-! CHECK-NEXT: return
end subroutine all_arguments
/*addLocArgs=*/false);
}
-TEST_F(RuntimeCallTest, genGetCommandArgument) {
+TEST_F(RuntimeCallTest, genArgumentValue) {
mlir::Location loc = firBuilder->getUnknownLoc();
mlir::Type intTy = firBuilder->getDefaultIntegerType();
mlir::Type charTy = fir::BoxType::get(firBuilder->getNoneType());
mlir::Value number = firBuilder->create<fir::UndefOp>(loc, intTy);
mlir::Value value = firBuilder->create<fir::UndefOp>(loc, charTy);
mlir::Value errmsg = firBuilder->create<fir::UndefOp>(loc, charTy);
- // genGetCommandArgument expects `length` and `status` to be memory references
- mlir::Value length = firBuilder->create<fir::AllocaOp>(loc, intTy);
- mlir::Value status = firBuilder->create<fir::AllocaOp>(loc, intTy);
+ mlir::Value result =
+ fir::runtime::genArgumentValue(*firBuilder, loc, number, value, errmsg);
+ checkCallOp(result.getDefiningOp(), "_FortranAArgumentValue", /*nbArgs=*/3,
+ /*addLocArgs=*/false);
+}
- fir::runtime::genGetCommandArgument(
- *firBuilder, loc, number, value, length, status, errmsg);
- checkCallOpFromResultBox(
- value, "_FortranAArgumentValue", /*nbArgs=*/3, /*addLocArgs=*/false);
- mlir::Block *block = firBuilder->getBlock();
- EXPECT_TRUE(block) << "Failed to retrieve the block!";
- checkBlockForCallOp(block, "_FortranAArgumentLength", /*nbArgs=*/1);
+TEST_F(RuntimeCallTest, genArgumentLen) {
+ mlir::Location loc = firBuilder->getUnknownLoc();
+ mlir::Type intTy = firBuilder->getDefaultIntegerType();
+ mlir::Value number = firBuilder->create<fir::UndefOp>(loc, intTy);
+ mlir::Value result =
+ fir::runtime::genArgumentLength(*firBuilder, loc, number);
+ checkCallOp(result.getDefiningOp(), "_FortranAArgumentLength", /*nbArgs=*/1,
+ /*addLocArgs=*/false);
}
-TEST_F(RuntimeCallTest, genGetEnvironmentVariable) {
+TEST_F(RuntimeCallTest, genEnvVariableValue) {
mlir::Location loc = firBuilder->getUnknownLoc();
mlir::Type intTy = firBuilder->getDefaultIntegerType();
mlir::Type charTy = fir::BoxType::get(firBuilder->getNoneType());
- mlir::Value number = firBuilder->create<fir::UndefOp>(loc, intTy);
+ mlir::Value name = firBuilder->create<fir::UndefOp>(loc, charTy);
mlir::Value value = firBuilder->create<fir::UndefOp>(loc, charTy);
mlir::Value trimName = firBuilder->create<fir::UndefOp>(loc, i1Ty);
mlir::Value errmsg = firBuilder->create<fir::UndefOp>(loc, charTy);
- // genGetCommandArgument expects `length` and `status` to be memory references
- mlir::Value length = firBuilder->create<fir::AllocaOp>(loc, intTy);
- mlir::Value status = firBuilder->create<fir::AllocaOp>(loc, intTy);
+ mlir::Value result = fir::runtime::genEnvVariableValue(
+ *firBuilder, loc, name, value, trimName, errmsg);
+ checkCallOp(result.getDefiningOp(), "_FortranAEnvVariableValue", /*nbArgs=*/4,
+ /*addLocArgs=*/true);
+}
- fir::runtime::genGetEnvironmentVariable(
- *firBuilder, loc, number, value, length, status, trimName, errmsg);
- checkCallOpFromResultBox(
- value, "_FortranAEnvVariableValue", /*nbArgs=*/6, /*addLocArgs=*/false);
- mlir::Block *block = firBuilder->getBlock();
- EXPECT_TRUE(block) << "Failed to retrieve the block!";
- checkBlockForCallOp(block, "_FortranAEnvVariableLength", /*nbArgs=*/4);
+TEST_F(RuntimeCallTest, genEnvVariableLength) {
+ mlir::Location loc = firBuilder->getUnknownLoc();
+ mlir::Type intTy = firBuilder->getDefaultIntegerType();
+ mlir::Type charTy = fir::BoxType::get(firBuilder->getNoneType());
+ mlir::Value name = firBuilder->create<fir::UndefOp>(loc, charTy);
+ mlir::Value trimName = firBuilder->create<fir::UndefOp>(loc, i1Ty);
+ mlir::Value result =
+ fir::runtime::genEnvVariableLength(*firBuilder, loc, name, trimName);
+ checkCallOp(result.getDefiningOp(), "_FortranAEnvVariableLength",
+ /*nbArgs=*/2, /*addLocArgs=*/true);
}