[flang] Lower command and environment intrinsics

This patch adds lowering for command and environment
related intrinsics:
- `get_command_argument`
- `get_environment_variable`
- `command_argument_count`

This patch is part of the upstreaming effort from fir-dev branch.

Reviewed By: PeteSteinfeld

Differential Revision: https://reviews.llvm.org/D121909

Co-authored-by: Josh Mottley <Josh.Mottley@arm.com>
Co-authored-by: Jean Perier <jperier@nvidia.com>
This commit is contained in:
Valentin Clement 2022-03-17 14:34:58 +01:00
parent 151c144350
commit 2b55850df8
No known key found for this signature in database
GPG Key ID: 086D54783C928776
4 changed files with 410 additions and 0 deletions

View File

@ -25,6 +25,7 @@
#include "flang/Optimizer/Builder/FIRBuilder.h"
#include "flang/Optimizer/Builder/MutableBox.h"
#include "flang/Optimizer/Builder/Runtime/Character.h"
#include "flang/Optimizer/Builder/Runtime/Command.h"
#include "flang/Optimizer/Builder/Runtime/Inquiry.h"
#include "flang/Optimizer/Builder/Runtime/Numeric.h"
#include "flang/Optimizer/Builder/Runtime/RTBuilder.h"
@ -445,6 +446,8 @@ struct IntrinsicLibrary {
mlir::Value genBtest(mlir::Type, llvm::ArrayRef<mlir::Value>);
mlir::Value genCeiling(mlir::Type, llvm::ArrayRef<mlir::Value>);
fir::ExtendedValue genChar(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
fir::ExtendedValue
genCommandArgumentCount(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
fir::ExtendedValue genCount(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
template <mlir::arith::CmpIPredicate pred>
fir::ExtendedValue genCharacterCompare(mlir::Type,
@ -463,6 +466,8 @@ struct IntrinsicLibrary {
mlir::Value genFloor(mlir::Type, llvm::ArrayRef<mlir::Value>);
mlir::Value genFraction(mlir::Type resultType,
mlir::ArrayRef<mlir::Value> args);
void genGetCommandArgument(mlir::ArrayRef<fir::ExtendedValue> args);
void genGetEnvironmentVariable(llvm::ArrayRef<fir::ExtendedValue>);
/// Lowering for the IAND intrinsic. The IAND intrinsic expects two arguments
/// in the llvm::ArrayRef.
mlir::Value genIand(mlir::Type, llvm::ArrayRef<mlir::Value>);
@ -634,6 +639,7 @@ static constexpr IntrinsicHandler handlers[]{
{"btest", &I::genBtest},
{"ceiling", &I::genCeiling},
{"char", &I::genChar},
{"command_argument_count", &I::genCommandArgumentCount},
{"count",
&I::genCount,
{{{"mask", asAddr}, {"dim", asValue}, {"kind", asValue}}},
@ -672,6 +678,23 @@ static constexpr IntrinsicHandler handlers[]{
{"exponent", &I::genExponent},
{"floor", &I::genFloor},
{"fraction", &I::genFraction},
{"get_command_argument",
&I::genGetCommandArgument,
{{{"number", asValue},
{"value", asAddr},
{"length", asAddr},
{"status", asAddr},
{"errmsg", asAddr}}},
/*isElemental=*/false},
{"get_environment_variable",
&I::genGetEnvironmentVariable,
{{{"name", asValue},
{"value", asAddr},
{"length", asAddr},
{"status", asAddr},
{"trim_name", asValue},
{"errmsg", asAddr}}},
/*isElemental=*/false},
{"iachar", &I::genIchar},
{"iand", &I::genIand},
{"ibclr", &I::genIbclr},
@ -1843,6 +1866,17 @@ IntrinsicLibrary::genChar(mlir::Type type,
return fir::CharBoxValue{cast, len};
}
// COMMAND_ARGUMENT_COUNT
fir::ExtendedValue IntrinsicLibrary::genCommandArgumentCount(
mlir::Type resultType, llvm::ArrayRef<fir::ExtendedValue> args) {
assert(args.size() == 0);
assert(resultType == builder.getDefaultIntegerType() &&
"result type is not default integer kind type");
return builder.createConvert(
loc, resultType, fir::runtime::genCommandArgumentCount(builder, loc));
;
}
// COUNT
fir::ExtendedValue
IntrinsicLibrary::genCount(mlir::Type resultType,
@ -2096,6 +2130,105 @@ mlir::Value IntrinsicLibrary::genFraction(mlir::Type resultType,
fir::runtime::genFraction(builder, loc, fir::getBase(args[0])));
}
// GET_COMMAND_ARGUMENT
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]);
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);
}
// GET_ENVIRONMENT_VARIABLE
void IntrinsicLibrary::genGetEnvironmentVariable(
llvm::ArrayRef<fir::ExtendedValue> args) {
assert(args.size() == 6);
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 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 TRIM_NAME argument
mlir::Value trim_name =
isAbsent(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);
}
// IAND
mlir::Value IntrinsicLibrary::genIand(mlir::Type resultType,
llvm::ArrayRef<mlir::Value> args) {

View File

@ -0,0 +1,11 @@
! RUN: bbc -emit-fir %s -o - | FileCheck %s
! bbc doesn't have a way to set the default kinds so we use flang-new driver
! RUN: flang-new -fc1 -fdefault-integer-8 -emit-fir %s -o - | FileCheck --check-prefixes=CHECK,CHECK-64 %s
! CHECK-LABEL: argument_count_test
subroutine argument_count_test()
integer :: arg_count_test
arg_count_test = command_argument_count()
! CHECK: %[[argumentCount:.*]] = fir.call @_FortranAArgumentCount() : () -> i32
! CHECK-64: %{{[0-9]+}} = fir.convert %[[argumentCount]] : (i32) -> i64
end subroutine argument_count_test

View File

@ -0,0 +1,106 @@
! RUN: bbc -emit-fir %s -o - | FileCheck --check-prefixes=CHECK,CHECK-32 -DDEFAULT_INTEGER_SIZE=32 %s
! RUN: flang-new -fc1 -fdefault-integer-8 -emit-fir %s -o - | FileCheck --check-prefixes=CHECK,CHECK-64 -DDEFAULT_INTEGER_SIZE=64 %s
! CHECK-LABEL: func @_QPnumber_only(
! CHECK-SAME: %[[num:.*]]: !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>{{.*}}) {
subroutine number_only(num)
integer :: num
call get_command_argument(num)
! CHECK-NOT: fir.call @_FortranAArgumentValue
! CHECK-NOT: fir.call @_FortranAArgumentLength
! CHECK-NEXT: return
end subroutine number_only
! CHECK-LABEL: func @_QPnumber_and_value_only(
! CHECK-SAME: %[[num:.*]]: !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>{{.*}}, %[[value:.*]]: !fir.boxchar<1>{{.*}}) {
subroutine number_and_value_only(num, value)
integer :: num
character(len=32) :: value
call get_command_argument(num, value)
! CHECK: %[[valueUnboxed:.*]]:2 = fir.unboxchar %[[value]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
! CHECK-NEXT: %[[valueLength:.*]] = arith.constant 32 : index
! CHECK-NEXT: %[[numUnbox:.*]] = fir.load %[[num]] : !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>
! CHECK-NEXT: %[[valueBoxed:.*]] = fir.embox %[[valueUnboxed]]#0 typeparams %[[valueLength]] : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>>
! CHECK-NEXT: %[[errmsg:.*]] = fir.absent !fir.box<none>
! CHECK-64-NEXT: %[[numCast:.*]] = fir.convert %[[numUnbox]] : (i64) -> i32
! CHECK-NEXT: %[[valueCast:.*]] = fir.convert %[[valueBoxed]] : (!fir.box<!fir.char<1,?>>) -> !fir.box<none>
! CHECK-32-NEXT: %{{[0-9]+}} = fir.call @_FortranAArgumentValue(%[[numUnbox]], %[[valueCast]], %[[errmsg]]) : (i32, !fir.box<none>, !fir.box<none>) -> i32
! CHECK-64-NEXT: %{{[0-9]+}} = fir.call @_FortranAArgumentValue(%[[numCast]], %[[valueCast]], %[[errmsg]]) : (i32, !fir.box<none>, !fir.box<none>) -> i32
! CHECK-NOT: fir.call @_FortranAArgumentLength
end subroutine number_and_value_only
! CHECK-LABEL: func @_QPall_arguments(
! CHECK-SAME: %[[num:[^:]*]]: !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>{{.*}}, %[[value:.*]]: !fir.boxchar<1>{{.*}}, %[[length:[^:]*]]: !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>{{.*}}, %[[status:.*]]: !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>{{.*}}, %[[errmsg:.*]]: !fir.boxchar<1>{{.*}}) {
subroutine all_arguments(num, value, length, status, errmsg)
integer :: num, length, status
character(len=32) :: value, errmsg
call get_command_argument(num, value, length, status, errmsg)
! CHECK: %[[errmsgUnboxed:.*]]:2 = fir.unboxchar %[[errmsg]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
! CHECK-NEXT: %[[errmsgLen:.*]] = arith.constant 32 : index
! CHECK-NEXT: %[[valueUnboxed:.*]]:2 = fir.unboxchar %[[value]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
! CHECK-NEXT: %[[valueLen:.*]] = arith.constant 32 : index
! CHECK-NEXT: %[[numUnboxed:.*]] = fir.load %[[num]] : !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>
! CHECK-NEXT: %[[valueBoxed:.*]] = fir.embox %[[valueUnboxed]]#0 typeparams %[[valueLen]] : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>>
! CHECK-NEXT: %[[errmsgBoxed:.*]] = fir.embox %[[errmsgUnboxed]]#0 typeparams %[[errmsgLen]] : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>>
! CHECK-64-NEXT: %[[numCast:.*]] = fir.convert %[[numUnboxed]] : (i64) -> i32
! CHECK-NEXT: %[[valueBuffer:.*]] = fir.convert %[[valueBoxed]] : (!fir.box<!fir.char<1,?>>) -> !fir.box<none>
! 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-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
! CHECK-LABEL: func @_QPnumber_and_length_only(
! CHECK-SAME: %[[num:.*]]: !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>{{.*}}, %[[length:.*]]: !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>{{.*}}) {
subroutine number_and_length_only(num, length)
integer :: num, length
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-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-SAME: %[[num:.*]]: !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>{{.*}}, %[[status:.*]]: !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>{{.*}}) {
subroutine number_and_status_only(num, status)
integer :: num, status
call get_command_argument(num, STATUS=status)
! 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-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-NOT: fir.call @_FortranAArgumentLength
end subroutine number_and_status_only
! CHECK-LABEL: func @_QPnumber_and_errmsg_only(
! CHECK-SAME: %[[num:.*]]: !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>{{.*}}, %[[errmsg:.*]]: !fir.boxchar<1>{{.*}}) {
subroutine number_and_errmsg_only(num, errmsg)
integer :: num
character(len=32) :: errmsg
call get_command_argument(num, ERRMSG=errmsg)
! 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: %[[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
! CHECK-NOT: fir.call @_FortranAArgumentLength
end subroutine number_and_errmsg_only

View File

@ -0,0 +1,160 @@
! RUN: bbc -emit-fir %s -o - | FileCheck --check-prefixes=CHECK,CHECK-32 -DDEFAULT_INTEGER_SIZE=32 %s
! RUN: flang-new -fc1 -fdefault-integer-8 -emit-fir %s -o - | FileCheck --check-prefixes=CHECK,CHECK-64 -DDEFAULT_INTEGER_SIZE=64 %s
! CHECK-LABEL: func @_QPnumber_only(
! CHECK-SAME: %[[nameArg:.*]]: !fir.boxchar<1> {fir.bindc_name = "name"}) {
subroutine number_only(name)
character(len=32) :: name
call get_environment_variable(name)
! CHECK-NOT: fir.call @_FortranAEnvVariableValue
! CHECK-NOT: fir.call @_FortranAEnvVariableLength
! CHECK-NEXT: return
end subroutine number_only
! CHECK-LABEL: func @_QPname_and_value_only(
! CHECK-SAME: %[[nameArg:.*]]: !fir.boxchar<1> {fir.bindc_name = "name"},
! CHECK-SAME: %[[valueArg:.*]]: !fir.boxchar<1> {fir.bindc_name = "value"}) {
subroutine name_and_value_only(name, value)
character(len=32) :: name, value
call get_environment_variable(name, value)
! CHECK: %[[nameUnbox:.*]]:2 = fir.unboxchar %[[nameArg]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
! 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: %[[nameBox:.*]] = fir.embox %[[nameUnbox]]#0 typeparams %[[nameLength]] : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>>
! CHECK-NEXT: %[[valueBox:.*]] = fir.embox %[[valueUnbox]]#0 typeparams %[[valueLength]] : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>>
! CHECK-NEXT: %true = arith.constant true
! 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 - 10]] : i32
! CHECK-NEXT: %[[name:.*]] = fir.convert %[[nameBox]] : (!fir.box<!fir.char<1,?>>) -> !fir.box<none>
! CHECK-NEXT: %[[value:.*]] = fir.convert %[[valueBox]] : (!fir.box<!fir.char<1,?>>) -> !fir.box<none>
! CHECK-NEXT: %[[sourceFile:.*]] = fir.convert %[[sourceFileString]] : (!fir.ref<!fir.char<1,[[sourceFileLength]]>>) -> !fir.ref<i8>
! CHECK-NEXT: %{{[0-9]+}} = 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-NEXT: return
end subroutine name_and_value_only
! CHECK-LABEL: func @_QPname_and_length_only(
! CHECK-SAME: %[[nameArg:.*]]: !fir.boxchar<1> {fir.bindc_name = "name"},
! CHECK-SAME: %[[lengthArg:.*]]: !fir.ref<i[[DEFAULT_INTEGER_SIZE]]> {fir.bindc_name = "length"}) {
subroutine name_and_length_only(name, length)
character(len=32) :: name
integer :: length
call get_environment_variable(name, LENGTH=length)
! CHECK-NOT: fir.call @_FortranAEnvVariableValue
! 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 %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-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-32-NEXT: %[[length64:.*]] = fir.call @_FortranAEnvVariableLength(%[[name]], %true, %[[sourceFile]], %[[sourceLine]]) : (!fir.box<none>, i1, !fir.ref<i8>, i32) -> i64
! 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-SAME: %[[nameArg:.*]]: !fir.boxchar<1> {fir.bindc_name = "name"},
! CHECK-SAME: %[[statusArg:.*]]: !fir.ref<i[[DEFAULT_INTEGER_SIZE]]> {fir.bindc_name = "status"}) {
subroutine name_and_status_only(name, status)
character(len=32) :: name
integer :: status
call get_environment_variable(name, STATUS=status)
! 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: %[[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: %[[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-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
end subroutine name_and_status_only
! CHECK-LABEL: func @_QPname_and_trim_name_only(
! CHECK-SAME: %[[nameArg:.*]]: !fir.boxchar<1> {fir.bindc_name = "name"},
! CHECK-SAME: %[[trimNameArg:.*]]: !fir.ref<!fir.logical<4>> {fir.bindc_name = "trim_name"}) {
subroutine name_and_trim_name_only(name, trim_name)
character(len=32) :: name
logical :: trim_name
call get_environment_variable(name, TRIM_NAME=trim_name)
! CHECK-NOT: fir.call @_FortranAEnvVariableValue
! CHECK-NOT: fir.call @_FortranAEnvVariableLength
! CHECK-NEXT: return
end subroutine name_and_trim_name_only
! CHECK-LABEL: func @_QPname_and_errmsg_only(
! CHECK-SAME: %[[nameArg:.*]]: !fir.boxchar<1> {fir.bindc_name = "name"},
! CHECK-SAME: %[[errmsgArg:.*]]: !fir.boxchar<1> {fir.bindc_name = "errmsg"}) {
subroutine name_and_errmsg_only(name, errmsg)
character(len=32) :: name, errmsg
call get_environment_variable(name, ERRMSG=errmsg)
! CHECK: %[[errmsgUnbox:.*]]:2 = fir.unboxchar %[[errmsgArg]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
! CHECK-NEXT: %[[errmsgLength:.*]] = arith.constant 32 : index
! 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: %[[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: %[[errmsg:.*]] = fir.convert %[[errmsgBox]] : (!fir.box<!fir.char<1,?>>) -> !fir.box<none>
! CHECK-NEXT: %[[sourceFile:.*]] = fir.convert %[[sourceFileString]] : (!fir.ref<!fir.char<1,[[sourceFileLength]]>>) -> !fir.ref<i8>
! CHECK-NEXT: %{{[0-9]+}} = 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-NEXT: return
end subroutine name_and_errmsg_only
! CHECK-LABEL: func @_QPall_arguments(
! CHECK-SAME: %[[nameArg:[^:]*]]: !fir.boxchar<1> {fir.bindc_name = "name"},
! CHECK-SAME: %[[valueArg:.*]]: !fir.boxchar<1> {fir.bindc_name = "value"},
! CHECK-SAME: %[[lengthArg:[^:]*]]: !fir.ref<i[[DEFAULT_INTEGER_SIZE]]> {fir.bindc_name = "length"},
! CHECK-SAME: %[[statusArg:.*]]: !fir.ref<i[[DEFAULT_INTEGER_SIZE]]> {fir.bindc_name = "status"},
! CHECK-SAME: %[[trimNameArg:.*]]: !fir.ref<!fir.logical<4>> {fir.bindc_name = "trim_name"},
! CHECK-SAME: %[[errmsgArg:.*]]: !fir.boxchar<1> {fir.bindc_name = "errmsg"}) {
subroutine all_arguments(name, value, length, status, trim_name, errmsg)
character(len=32) :: name, value, errmsg
integer :: length, status
logical :: trim_name
call get_environment_variable(name, value, length, status, trim_name, errmsg)
! CHECK: %[[errmsgUnbox:.*]]:2 = fir.unboxchar %[[errmsgArg]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
! CHECK-NEXT: %[[errmsgLength:.*]] = arith.constant 32 : index
! 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: %[[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-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-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: fir.store %[[result]] to %[[lengthArg]] : !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>
! CHECK-NEXT: return
end subroutine all_arguments