diff --git a/flang/include/flang/Optimizer/Builder/FIRBuilder.h b/flang/include/flang/Optimizer/Builder/FIRBuilder.h --- a/flang/include/flang/Optimizer/Builder/FIRBuilder.h +++ b/flang/include/flang/Optimizer/Builder/FIRBuilder.h @@ -247,6 +247,11 @@ 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, diff --git a/flang/include/flang/Optimizer/Builder/Runtime/Command.h b/flang/include/flang/Optimizer/Builder/Runtime/Command.h --- a/flang/include/flang/Optimizer/Builder/Runtime/Command.h +++ b/flang/include/flang/Optimizer/Builder/Runtime/Command.h @@ -23,23 +23,35 @@ /// 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 diff --git a/flang/lib/Lower/IntrinsicCall.cpp b/flang/lib/Lower/IntrinsicCall.cpp --- a/flang/lib/Lower/IntrinsicCall.cpp +++ b/flang/lib/Lower/IntrinsicCall.cpp @@ -737,19 +737,19 @@ {"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}, @@ -2399,100 +2399,119 @@ void IntrinsicLibrary::genGetCommandArgument( llvm::ArrayRef args) { assert(args.size() == 5); - - auto processCharBox = [&](llvm::Optional arg, - mlir::Value &value) -> void { - if (arg.hasValue()) { - value = builder.createBox(loc, *arg); - } else { - value = builder - .create( - 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 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 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(loc, boxNoneTy).getResult(); + mlir::Value errBox = + isStaticallyPresent(errmsg) + ? fir::getBase(errmsg) + : builder.create(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 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 arg, - mlir::Value &value) -> void { - if (arg.hasValue()) { - value = builder.createBox(loc, *arg); - } else { - value = builder - .create( - loc, fir::BoxType::get(builder.getNoneType())) - .getResult(); - } - }; - - // Handle NAME argument - mlir::Value name; - if (const fir::CharBoxValue *charBox = args[0].getCharBox()) { - llvm::Optional 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(loc, trimNameAddr); + mlir::Value cast = builder.createConvert(loc, i1Ty, trimLoad); + builder.create(loc, cast); + }) + .genElse([&]() { + mlir::Value trueVal = builder.createBool(loc, true); + builder.create(loc, trueVal); + }) + .getResults()[0]; } - // Handle optional VALUE argument - mlir::Value value; - llvm::Optional 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(loc, boxNoneTy).getResult(); + mlir::Value errBox = + isStaticallyPresent(errmsg) + ? fir::getBase(errmsg) + : builder.create(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 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 diff --git a/flang/lib/Optimizer/Builder/FIRBuilder.cpp b/flang/lib/Optimizer/Builder/FIRBuilder.cpp --- a/flang/lib/Optimizer/Builder/FIRBuilder.cpp +++ b/flang/lib/Optimizer/Builder/FIRBuilder.cpp @@ -334,6 +334,14 @@ 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(loc, cast, addr); +} + fir::StringLitOp fir::FirOpBuilder::createStringLitOp(mlir::Location loc, llvm::StringRef data) { auto type = fir::CharacterType::get(getContext(), 1, data.size()); diff --git a/flang/lib/Optimizer/Builder/Runtime/Command.cpp b/flang/lib/Optimizer/Builder/Runtime/Command.cpp --- a/flang/lib/Optimizer/Builder/Runtime/Command.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Command.cpp @@ -32,96 +32,55 @@ return builder.create(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(loc, builder); + llvm::SmallVector args = fir::runtime::createArguments( + builder, loc, argumentValueFunc.getFunctionType(), number, value, errmsg); + return builder.create(loc, argumentValueFunc, args).getResult(0); +} + +mlir::Value fir::runtime::genArgumentLength(fir::FirOpBuilder &builder, + mlir::Location loc, + mlir::Value number) { auto argumentLengthFunc = fir::runtime::getRuntimeFunc(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 args = fir::runtime::createArguments( - builder, loc, argumentValueFunc.getFunctionType(), number, value, - errmsg); - valueResult = - builder.create(loc, argumentValueFunc, args).getResult(0); - } - - // Only save result of `ArgumentValue` if "STATUS" parameter has been given - if (status) { - const mlir::Value statusLoaded = builder.create(loc, status); - mlir::Value resultCast = - builder.createConvert(loc, statusLoaded.getType(), valueResult); - builder.create(loc, resultCast, status); - } - - // Only run `ArgumentLength` intrinsic if "LENGTH" parameter provided - if (length) { - llvm::SmallVector args = fir::runtime::createArguments( - builder, loc, argumentLengthFunc.getFunctionType(), number); - mlir::Value result = - builder.create(loc, argumentLengthFunc, args).getResult(0); - const mlir::Value valueLoaded = builder.create(loc, length); - mlir::Value resultCast = - builder.createConvert(loc, valueLoaded.getType(), result); - builder.create(loc, resultCast, length); - } + llvm::SmallVector args = fir::runtime::createArguments( + builder, loc, argumentLengthFunc.getFunctionType(), number); + return builder.create(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(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 args = + fir::runtime::createArguments(builder, loc, valueFuncTy, name, value, + trimName, errmsg, sourceFile, sourceLine); + return builder.create(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(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 args = fir::runtime::createArguments( - builder, loc, valueFunc.getFunctionType(), name, value, trimName, - errmsg, sourceFile, sourceLine); - valueResult = - builder.create(loc, valueFunc, args).getResult(0); - } - - // Only save result of `EnvVariableValue` if "STATUS" parameter provided - if (status) { - const mlir::Value statusLoaded = builder.create(loc, status); - mlir::Value resultCast = - builder.createConvert(loc, statusLoaded.getType(), valueResult); - builder.create(loc, resultCast, status); - } - - // Only run `EnvVariableLength` intrinsic if "LENGTH" parameter provided - if (length) { - llvm::SmallVector args = fir::runtime::createArguments( - builder, loc, lengthFunc.getFunctionType(), name, trimName, sourceFile, - sourceLine); - mlir::Value result = - builder.create(loc, lengthFunc, args).getResult(0); - const mlir::Value lengthLoaded = builder.create(loc, length); - mlir::Value resultCast = - builder.createConvert(loc, lengthLoaded.getType(), result); - builder.create(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 args = fir::runtime::createArguments( + builder, loc, lengthFuncTy, name, trimName, sourceFile, sourceLine); + return builder.create(loc, lengthFunc, args).getResult(0); } diff --git a/flang/test/Lower/Intrinsics/get_command_argument-optional.f90 b/flang/test/Lower/Intrinsics/get_command_argument-optional.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Lower/Intrinsics/get_command_argument-optional.f90 @@ -0,0 +1,43 @@ +! 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 {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 {fir.bindc_name = "length", fir.optional}, +! CHECK-SAME: %[[VAL_3:.*]]: !fir.ref {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>, index) +! CHECK: %[[VAL_6:.*]]:2 = fir.unboxchar %[[VAL_1]] : (!fir.boxchar<1>) -> (!fir.ref>, index) +! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_0]] : !fir.ref +! CHECK: %[[VAL_8:.*]] = fir.is_present %[[VAL_6]]#0 : (!fir.ref>) -> i1 +! CHECK: %[[VAL_9:.*]] = fir.embox %[[VAL_6]]#0 typeparams %[[VAL_6]]#1 : (!fir.ref>, index) -> !fir.box> +! CHECK: %[[VAL_10:.*]] = fir.absent !fir.box> +! CHECK: %[[VAL_11:.*]] = arith.select %[[VAL_8]], %[[VAL_9]], %[[VAL_10]] : !fir.box> +! CHECK: %[[VAL_12:.*]] = fir.is_present %[[VAL_5]]#0 : (!fir.ref>) -> i1 +! CHECK: %[[VAL_13:.*]] = fir.embox %[[VAL_5]]#0 typeparams %[[VAL_5]]#1 : (!fir.ref>, index) -> !fir.box> +! CHECK: %[[VAL_14:.*]] = fir.absent !fir.box> +! CHECK: %[[VAL_15:.*]] = arith.select %[[VAL_12]], %[[VAL_13]], %[[VAL_14]] : !fir.box> +! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_11]] : (!fir.box>) -> !fir.box +! CHECK: %[[VAL_17:.*]] = fir.convert %[[VAL_15]] : (!fir.box>) -> !fir.box +! CHECK: %[[VAL_18:.*]] = fir.call @_FortranAArgumentValue(%[[VAL_7]], %[[VAL_16]], %[[VAL_17]]) : (i32, !fir.box, !fir.box) -> i32 +! CHECK: %[[VAL_19:.*]] = fir.convert %[[VAL_3]] : (!fir.ref) -> 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 +! CHECK: } +! CHECK: %[[VAL_22:.*]] = fir.convert %[[VAL_2]] : (!fir.ref) -> 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 +! CHECK: } +end subroutine diff --git a/flang/test/Lower/Intrinsics/get_command_argument.f90 b/flang/test/Lower/Intrinsics/get_command_argument.f90 --- a/flang/test/Lower/Intrinsics/get_command_argument.f90 +++ b/flang/test/Lower/Intrinsics/get_command_argument.f90 @@ -47,11 +47,11 @@ ! CHECK-NEXT: %[[errmsgBuffer:.*]] = fir.convert %[[errmsgBoxed]] : (!fir.box>) -> !fir.box ! CHECK-32-NEXT: %[[statusResult:.*]] = fir.call @_FortranAArgumentValue(%[[numUnboxed]], %[[valueBuffer]], %[[errmsgBuffer]]) : (i32, !fir.box, !fir.box) -> i32 ! CHECK-64-NEXT: %[[statusResult32:.*]] = fir.call @_FortranAArgumentValue(%[[numCast]], %[[valueBuffer]], %[[errmsgBuffer]]) : (i32, !fir.box, !fir.box) -> i32 -! CHECK-64-NEXT: %[[statusResult:.*]] = fir.convert %[[statusResult32]] : (i32) -> i64 -! CHECK-NEXT: fir.store %[[statusResult]] to %[[status]] : !fir.ref -! 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 +! 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 end subroutine all_arguments @@ -63,12 +63,11 @@ call get_command_argument(num, LENGTH=length) ! CHECK-NOT: fir.call @_FortranAArgumentValue ! CHECK: %[[numLoaded:.*]] = fir.load %[[num]] : !fir.ref -! 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 -! CHECK-NEXT: return end subroutine number_and_length_only ! CHECK-LABEL: func @_QPnumber_and_status_only( @@ -79,11 +78,11 @@ ! CHECK: %[[numLoaded:.*]] = fir.load %[[num]] : !fir.ref ! CHECK-NEXT: %[[value:.*]] = fir.absent !fir.box ! CHECK-NEXT: %[[errmsg:.*]] = fir.absent !fir.box -! 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, !fir.box) -> i32 ! CHECK-64-NEXT: %[[result32:.*]] = fir.call @_FortranAArgumentValue(%[[numCast]], %[[value]], %[[errmsg]]) : (i32, !fir.box, !fir.box) -> i32 -! CHECK-64-NEXT: %[[result:.*]] = fir.convert %[[result32]] : (i32) -> i64 -! CHECK-32-NEXT: fir.store %[[result]] to %[[status]] : !fir.ref +! CHECK-64: %[[result:.*]] = fir.convert %[[result32]] : (i32) -> i64 +! CHECK-32: fir.store %[[result]] to %[[status]] : !fir.ref ! CHECK-NOT: fir.call @_FortranAArgumentLength end subroutine number_and_status_only @@ -96,9 +95,9 @@ ! CHECK: %[[errmsgUnboxed:.*]]:2 = fir.unboxchar %[[errmsg]] : (!fir.boxchar<1>) -> (!fir.ref>, index) ! CHECK-NEXT: %[[errmsgLength:.*]] = arith.constant 32 : index ! CHECK-NEXT: %[[numUnboxed:.*]] = fir.load %[[num]] : !fir.ref -! CHECK-NEXT: %[[value:.*]] = fir.absent !fir.box ! CHECK-NEXT: %[[errmsgBoxed:.*]] = fir.embox %[[errmsgUnboxed]]#0 typeparams %[[errmsgLength]] : (!fir.ref>, index) -> !fir.box> -! CHECK-64-NEXT: %[[numCast:.*]] = fir.convert %[[numUnboxed]] : (i64) -> i32 +! CHECK-NEXT: %[[value:.*]] = fir.absent !fir.box +! CHECK-64: %[[numCast:.*]] = fir.convert %[[numUnboxed]] : (i64) -> i32 ! CHECK-NEXT: %[[errmsg:.*]] = fir.convert %[[errmsgBoxed]] : (!fir.box>) -> !fir.box ! CHECK-32-NEXT: %{{[0-9]+}} = fir.call @_FortranAArgumentValue(%[[numUnboxed]], %[[value]], %[[errmsg]]) : (i32, !fir.box, !fir.box) -> i32 ! CHECK-64-NEXT: %{{[0-9]+}} = fir.call @_FortranAArgumentValue(%[[numCast]], %[[value]], %[[errmsg]]) : (i32, !fir.box, !fir.box) -> i32 diff --git a/flang/test/Lower/Intrinsics/get_environment_variable-optional.f90 b/flang/test/Lower/Intrinsics/get_environment_variable-optional.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Lower/Intrinsics/get_environment_variable-optional.f90 @@ -0,0 +1,60 @@ +! 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 {fir.bindc_name = "length", fir.optional}, +! CHECK-SAME: %[[VAL_3:.*]]: !fir.ref {fir.bindc_name = "status", fir.optional}, +! CHECK-SAME: %[[VAL_4:.*]]: !fir.ref> {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>, index) +! CHECK: %[[VAL_7:.*]]:2 = fir.unboxchar %[[VAL_0]] : (!fir.boxchar<1>) -> (!fir.ref>, index) +! CHECK: %[[VAL_8:.*]]:2 = fir.unboxchar %[[VAL_1]] : (!fir.boxchar<1>) -> (!fir.ref>, index) +! CHECK: %[[VAL_9:.*]] = fir.embox %[[VAL_7]]#0 typeparams %[[VAL_7]]#1 : (!fir.ref>, index) -> !fir.box> +! CHECK: %[[VAL_10:.*]] = fir.is_present %[[VAL_8]]#0 : (!fir.ref>) -> i1 +! CHECK: %[[VAL_11:.*]] = fir.embox %[[VAL_8]]#0 typeparams %[[VAL_8]]#1 : (!fir.ref>, index) -> !fir.box> +! CHECK: %[[VAL_12:.*]] = fir.absent !fir.box> +! CHECK: %[[VAL_13:.*]] = arith.select %[[VAL_10]], %[[VAL_11]], %[[VAL_12]] : !fir.box> +! CHECK: %[[VAL_14:.*]] = fir.is_present %[[VAL_6]]#0 : (!fir.ref>) -> i1 +! CHECK: %[[VAL_15:.*]] = fir.embox %[[VAL_6]]#0 typeparams %[[VAL_6]]#1 : (!fir.ref>, index) -> !fir.box> +! CHECK: %[[VAL_16:.*]] = fir.absent !fir.box> +! CHECK: %[[VAL_17:.*]] = arith.select %[[VAL_14]], %[[VAL_15]], %[[VAL_16]] : !fir.box> +! CHECK: %[[VAL_18:.*]] = fir.convert %[[VAL_4]] : (!fir.ref>) -> 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> +! 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.box +! CHECK: %[[VAL_28:.*]] = fir.convert %[[VAL_13]] : (!fir.box>) -> !fir.box +! CHECK: %[[VAL_29:.*]] = fir.convert %[[VAL_17]] : (!fir.box>) -> !fir.box +! CHECK: %[[VAL_31:.*]] = fir.call @_FortranAEnvVariableValue(%[[VAL_27]], %[[VAL_28]], %[[VAL_32:.*]], %[[VAL_29]], %{{.*}}, %{{.*}}) : (!fir.box, !fir.box, i1, !fir.box, !fir.ref, i32) -> i32 +! CHECK: %[[VAL_33:.*]] = fir.convert %[[VAL_3]] : (!fir.ref) -> 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 +! CHECK: } +! CHECK: %[[VAL_36:.*]] = fir.convert %[[VAL_2]] : (!fir.ref) -> 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.box +! CHECK: %[[VAL_43:.*]] = fir.call @_FortranAEnvVariableLength(%[[VAL_41]], %[[VAL_32]], %{{.*}}, %{{.*}}) : (!fir.box, i1, !fir.ref, i32) -> i64 +! CHECK: %[[VAL_44:.*]] = fir.convert %[[VAL_43]] : (i64) -> i32 +! CHECK: fir.store %[[VAL_44]] to %[[VAL_2]] : !fir.ref +! CHECK: } +end subroutine diff --git a/flang/test/Lower/Intrinsics/get_environment_variable.f90 b/flang/test/Lower/Intrinsics/get_environment_variable.f90 --- a/flang/test/Lower/Intrinsics/get_environment_variable.f90 +++ b/flang/test/Lower/Intrinsics/get_environment_variable.f90 @@ -46,7 +46,7 @@ ! CHECK-NEXT: %[[nameLength:.*]] = arith.constant 32 : index ! CHECK-NEXT: %[[nameBox:.*]] = fir.embox %0#0 typeparams %[[nameLength]] : (!fir.ref>, index) -> !fir.box> ! CHECK-NEXT: %true = arith.constant true -! CHECK-NEXT: %[[sourceFileString:.*]] = fir.address_of(@_QQcl.{{.*}}) : !fir.ref> +! CHECK: %[[sourceFileString:.*]] = fir.address_of(@_QQcl.{{.*}}) : !fir.ref> ! CHECK-NEXT: %[[sourceLine:.*]] = arith.constant [[# @LINE - 7]] : i32 ! CHECK-NEXT: %[[name:.*]] = fir.convert %[[nameBox]] : (!fir.box>) -> !fir.box ! CHECK-NEXT: %[[sourceFile:.*]] = fir.convert %[[sourceFileString]] : (!fir.ref>) -> !fir.ref @@ -54,7 +54,6 @@ ! CHECK-64-NEXT: %[[length:.*]] = fir.call @_FortranAEnvVariableLength(%[[name]], %true, %[[sourceFile]], %[[sourceLine]]) : (!fir.box, i1, !fir.ref, i32) -> i64 ! CHECK-32-NEXT: %[[length:.*]] = fir.convert %[[length64]] : (i64) -> i32 ! CHECK-NEXT: fir.store %[[length]] to %[[lengthArg]] : !fir.ref -! CHECK-NEXT: return end subroutine name_and_length_only ! CHECK-LABEL: func @_QPname_and_status_only( @@ -67,8 +66,8 @@ ! CHECK: %[[nameUnbox:.*]]:2 = fir.unboxchar %[[nameArg]] : (!fir.boxchar<1>) -> (!fir.ref>, index) ! CHECK-NEXT: %[[nameLength:.*]] = arith.constant 32 : index ! CHECK-NEXT: %[[nameBox:.*]] = fir.embox %[[nameUnbox]]#0 typeparams %[[nameLength]] : (!fir.ref>, index) -> !fir.box> -! CHECK-NEXT: %[[value:.*]] = fir.absent !fir.box ! CHECK-NEXT: %true = arith.constant true +! CHECK-NEXT: %[[value:.*]] = fir.absent !fir.box ! CHECK-NEXT: %[[errmsg:.*]] = fir.absent !fir.box ! CHECK-NEXT: %[[sourceFileString:.*]] = fir.address_of(@_QQcl.{{.*}}) : !fir.ref> ! CHECK-NEXT: %[[sourceLine:.*]] = arith.constant [[# @LINE - 8]] : i32 @@ -76,9 +75,8 @@ ! CHECK-NEXT: %[[sourceFile:.*]] = fir.convert %[[sourceFileString]] : (!fir.ref>) -> !fir.ref ! CHECK-32-NEXT: %[[status:.*]] = fir.call @_FortranAEnvVariableValue(%[[name]], %[[value]], %true, %[[errmsg]], %[[sourceFile]], %[[sourceLine]]) : (!fir.box, !fir.box, i1, !fir.box, !fir.ref, i32) -> i32 ! CHECK-64-NEXT: %[[status32:.*]] = fir.call @_FortranAEnvVariableValue(%[[name]], %[[value]], %true, %[[errmsg]], %[[sourceFile]], %[[sourceLine]]) : (!fir.box, !fir.box, i1, !fir.box, !fir.ref, i32) -> i32 -! CHECK-64-NEXT: %[[status:.*]] = fir.convert %[[status32]] : (i32) -> i64 -! CHECK-NEXT: fir.store %[[status]] to %[[statusArg]] : !fir.ref -! CHECK-NEXT: return +! CHECK-64: %[[status:.*]] = fir.convert %[[status32]] : (i32) -> i64 +! CHECK: fir.store %[[status]] to %[[statusArg]] : !fir.ref end subroutine name_and_status_only ! CHECK-LABEL: func @_QPname_and_trim_name_only( @@ -104,9 +102,9 @@ ! CHECK-NEXT: %[[nameUnbox:.*]]:2 = fir.unboxchar %[[nameArg]] : (!fir.boxchar<1>) -> (!fir.ref>, index) ! CHECK-NEXT: %[[nameLength:.*]] = arith.constant 32 : index ! CHECK-NEXT: %[[nameBox:.*]] = fir.embox %[[nameUnbox]]#0 typeparams %[[nameLength]] : (!fir.ref>, index) -> !fir.box> -! CHECK-NEXT: %[[value:.*]] = fir.absent !fir.box -! CHECK-NEXT: %true = arith.constant true ! CHECK-NEXT: %[[errmsgBox:.*]] = fir.embox %[[errmsgUnbox]]#0 typeparams %c32 : (!fir.ref>, index) -> !fir.box> +! CHECK-NEXT: %true = arith.constant true +! CHECK-NEXT: %[[value:.*]] = fir.absent !fir.box ! CHECK-NEXT: %[[sourceFileString:.*]] = fir.address_of(@_QQcl.{{.*}}) : !fir.ref> ! CHECK-NEXT: %[[sourceLine:.*]] = arith.constant [[# @LINE - 10]] : i32 ! CHECK-NEXT: %[[name:.*]] = fir.convert %[[nameBox]] : (!fir.box>) -> !fir.box @@ -134,27 +132,33 @@ ! CHECK-NEXT: %[[nameLength:.*]] = arith.constant 32 : index ! CHECK-NEXT: %[[valueUnbox:.*]]:2 = fir.unboxchar %[[valueArg]] : (!fir.boxchar<1>) -> (!fir.ref>, index) ! CHECK-NEXT: %[[valueLength:.*]] = arith.constant 32 : index -! CHECK-NEXT: %[[trimNameLoaded:.*]] = fir.load %[[trimNameArg]] : !fir.ref> ! CHECK-NEXT: %[[nameBoxed:.*]] = fir.embox %[[nameUnbox]]#0 typeparams %[[nameLength]] : (!fir.ref>, index) -> !fir.box> ! CHECK-NEXT: %[[valueBoxed:.*]] = fir.embox %[[valueUnbox]]#0 typeparams %[[valueLength]] : (!fir.ref>, index) -> !fir.box> ! CHECK-NEXT: %[[errmsgBoxed:.*]] = fir.embox %[[errmsgUnbox]]#0 typeparams %[[errmsgLength]] : (!fir.ref>, index) -> !fir.box> -! CHECK-NEXT: %[[sourceFileString:.*]] = fir.address_of(@_QQcl.[[fileString:.*]]) : !fir.ref> -! CHECK-NEXT: %[[sourceLine:.*]] = arith.constant [[# @LINE - 12]] : i32 +! CHECK: %[[trimName:.*]] = fir.if %{{.*}} -> (i1) { +! CHECK-NEXT: %[[trimNameLoaded:.*]] = fir.load %[[trimNameArg]] : !fir.ref> +! 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> +! CHECK-NEXT: %[[sourceLine:.*]] = arith.constant [[# @LINE - 19]] : i32 ! CHECK-NEXT: %[[name:.*]] = fir.convert %[[nameBoxed]] : (!fir.box>) -> !fir.box ! CHECK-NEXT: %[[value:.*]] = fir.convert %[[valueBoxed]] : (!fir.box>) -> !fir.box -! CHECK-NEXT: %[[trimName:.*]] = fir.convert %[[trimNameLoaded]] : (!fir.logical<4>) -> i1 ! CHECK-NEXT: %[[errmsg:.*]] = fir.convert %[[errmsgBoxed]] : (!fir.box>) -> !fir.box ! CHECK-NEXT: %[[sourceFile:.*]] = fir.convert %[[sourceFileString]] : (!fir.ref>) -> !fir.ref ! CHECK-32-NEXT: %[[status:.*]] = fir.call @_FortranAEnvVariableValue(%[[name]], %[[value]], %[[trimName]], %[[errmsg]], %[[sourceFile]], %[[sourceLine]]) : (!fir.box, !fir.box, i1, !fir.box, !fir.ref, i32) -> i32 ! CHECK-64-NEXT: %[[status32:.*]] = fir.call @_FortranAEnvVariableValue(%[[name]], %[[value]], %[[trimName]], %[[errmsg]], %[[sourceFile]], %[[sourceLine]]) : (!fir.box, !fir.box, i1, !fir.box, !fir.ref, i32) -> i32 -! CHECK-64-NEXT: %[[status:.*]] = fir.convert %[[status32]] : (i32) -> i64 -! CHECK-NEXT: fir.store %[[status]] to %[[statusArg]] : !fir.ref +! CHECK-64: %[[status:.*]] = fir.convert %[[status32]] : (i32) -> i64 +! CHECK: fir.store %[[status]] to %[[statusArg]] : !fir.ref +! CHECK: %[[sourceFileString2:.*]] = fir.address_of(@_QQcl.[[fileString]]) : !fir.ref> +! CHECK-NEXT: %[[sourceLine2:.*]] = arith.constant [[# @LINE - 29]] : i32 ! CHECK-NEXT: %[[name:.*]] = fir.convert %[[nameBoxed]] : (!fir.box>) -> !fir.box -! CHECK-NEXT: %[[trimName:.*]] = fir.convert %[[trimNameLoaded]] : (!fir.logical<4>) -> i1 -! CHECK-NEXT: %[[sourceFile:.*]] = fir.convert %[[sourceFileString]] : (!fir.ref>) -> !fir.ref -! CHECK-32-NEXT: %[[result64:.*]] = fir.call @_FortranAEnvVariableLength(%[[name]], %[[trimName]], %[[sourceFile]], %[[sourceLine]]) : (!fir.box, i1, !fir.ref, i32) -> i64 -! CHECK-64-NEXT: %[[result:.*]] = fir.call @_FortranAEnvVariableLength(%[[name]], %[[trimName]], %[[sourceFile]], %[[sourceLine]]) : (!fir.box, i1, !fir.ref, i32) -> i64 -! CHECK-32-NEXT: %[[result:.*]] = fir.convert %[[result64]] : (i64) -> i32 +! CHECK-NEXT: %[[sourceFile2:.*]] = fir.convert %[[sourceFileString2]] : (!fir.ref>) -> !fir.ref +! CHECK-32-NEXT: %[[result64:.*]] = fir.call @_FortranAEnvVariableLength(%[[name]], %[[trimName]], %[[sourceFile2]], %[[sourceLine2]]) : (!fir.box, i1, !fir.ref, i32) -> i64 +! CHECK-64-NEXT: %[[result:.*]] = fir.call @_FortranAEnvVariableLength(%[[name]], %[[trimName]], %[[sourceFile2]], %[[sourceLine2]]) : (!fir.box, i1, !fir.ref, i32) -> i64 +! CHECK-32: %[[result:.*]] = fir.convert %[[result64]] : (i64) -> i32 ! CHECK-NEXT: fir.store %[[result]] to %[[lengthArg]] : !fir.ref -! CHECK-NEXT: return end subroutine all_arguments diff --git a/flang/unittests/Optimizer/Builder/Runtime/CommandTest.cpp b/flang/unittests/Optimizer/Builder/Runtime/CommandTest.cpp --- a/flang/unittests/Optimizer/Builder/Runtime/CommandTest.cpp +++ b/flang/unittests/Optimizer/Builder/Runtime/CommandTest.cpp @@ -17,43 +17,51 @@ /*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(loc, intTy); mlir::Value value = firBuilder->create(loc, charTy); mlir::Value errmsg = firBuilder->create(loc, charTy); - // genGetCommandArgument expects `length` and `status` to be memory references - mlir::Value length = firBuilder->create(loc, intTy); - mlir::Value status = firBuilder->create(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(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(loc, intTy); + mlir::Value name = firBuilder->create(loc, charTy); mlir::Value value = firBuilder->create(loc, charTy); mlir::Value trimName = firBuilder->create(loc, i1Ty); mlir::Value errmsg = firBuilder->create(loc, charTy); - // genGetCommandArgument expects `length` and `status` to be memory references - mlir::Value length = firBuilder->create(loc, intTy); - mlir::Value status = firBuilder->create(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(loc, charTy); + mlir::Value trimName = firBuilder->create(loc, i1Ty); + mlir::Value result = + fir::runtime::genEnvVariableLength(*firBuilder, loc, name, trimName); + checkCallOp(result.getDefiningOp(), "_FortranAEnvVariableLength", + /*nbArgs=*/2, /*addLocArgs=*/true); }