[flang] Single entry point for GET_ENVIRONMENT_VARIABLE

This patch refactors the runtime support for GET_ENVIRONMENT_VARIABLE
to have a single entry point instead of 2. It also updates lowering
accordingly.

This makes it easier to handle dynamically optional arguments.
See also https://reviews.llvm.org/D118777

Reviewed By: jeanPerier

Differential Revision: https://reviews.llvm.org/D142489
This commit is contained in:
Leandro Lupori 2023-01-19 17:45:19 +00:00
parent 764c88a50a
commit 48b5a06dfc
10 changed files with 184 additions and 236 deletions

View File

@ -39,21 +39,15 @@ mlir::Value genGetCommandArgument(fir::FirOpBuilder &, mlir::Location,
mlir::Value number, mlir::Value value,
mlir::Value length, mlir::Value errmsg);
/// 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);
/// Generate a call to GetEnvVariable runtime function which implements
/// the GET_ENVIRONMENT_VARIABLE intrinsic.
/// \p value, \p length 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 genGetEnvVariable(fir::FirOpBuilder &, mlir::Location,
mlir::Value name, mlir::Value value,
mlir::Value length, mlir::Value trimName,
mlir::Value errmsg);
} // namespace fir::runtime
#endif // FORTRAN_OPTIMIZER_BUILDER_RUNTIME_COMMAND_H

View File

@ -40,20 +40,12 @@ std::int32_t RTNAME(GetCommandArgument)(std::int32_t n,
int line = 0);
// 16.9.84 GET_ENVIRONMENT_VARIABLE
// We're breaking up the interface into several different functions, since most
// of the parameters are optional.
// Try to get the value of the environment variable specified by NAME.
// Returns a STATUS as described in the standard.
std::int32_t RTNAME(EnvVariableValue)(const Descriptor &name,
const Descriptor *value = nullptr, bool trim_name = true,
const Descriptor *errmsg = nullptr, const char *sourceFile = nullptr,
int line = 0);
// Try to get the significant length of the environment variable specified by
// NAME. Returns 0 if it doesn't manage.
std::int64_t RTNAME(EnvVariableLength)(const Descriptor &name,
bool trim_name = true, const char *sourceFile = nullptr, int line = 0);
std::int32_t RTNAME(GetEnvVariable)(const Descriptor &name,
const Descriptor *value = nullptr, const Descriptor *length = nullptr,
bool trim_name = true, const Descriptor *errmsg = nullptr,
const char *sourceFile = nullptr, int line = 0);
}
} // namespace Fortran::runtime

View File

@ -598,9 +598,9 @@ static constexpr IntrinsicHandler handlers[]{
&I::genGetEnvironmentVariable,
{{{"name", asBox},
{"value", asBox, handleDynamicOptional},
{"length", asAddr},
{"status", asAddr},
{"trim_name", asAddr},
{"length", asBox, handleDynamicOptional},
{"status", asAddr, handleDynamicOptional},
{"trim_name", asAddr, handleDynamicOptional},
{"errmsg", asBox, handleDynamicOptional}}},
/*isElemental=*/false},
{"iachar", &I::genIchar},
@ -3203,6 +3203,14 @@ void IntrinsicLibrary::genGetEnvironmentVariable(
const fir::ExtendedValue &trimName = args[4];
const fir::ExtendedValue &errmsg = args[5];
if (!name)
fir::emitFatalError(loc, "expected NAME parameter");
// If none of the optional parameters are present, do nothing.
if (!isStaticallyPresent(value) && !isStaticallyPresent(length) &&
!isStaticallyPresent(status) && !isStaticallyPresent(errmsg))
return;
// Handle optional TRIM_NAME argument
mlir::Value trim;
if (isStaticallyAbsent(trimName)) {
@ -3227,39 +3235,27 @@ void IntrinsicLibrary::genGetEnvironmentVariable(
.getResults()[0];
}
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.genIsNotNullAddr(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.genIsNotNullAddr(loc, lenAddr);
builder.genIfThen(loc, lenIsPresentAtRuntime)
.genThen([&]() {
mlir::Value len =
fir::runtime::genEnvVariableLength(builder, loc, name, trim);
builder.createStoreWithConvert(loc, len, lenAddr);
})
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 lenBox =
isStaticallyPresent(length)
? fir::getBase(length)
: 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::genGetEnvVariable(builder, loc, name, valBox,
lenBox, trim, errBox);
if (isStaticallyPresent(status)) {
mlir::Value statAddr = fir::getBase(status);
mlir::Value statIsPresentAtRuntime =
builder.genIsNotNullAddr(loc, statAddr);
builder.genIfThen(loc, statIsPresentAtRuntime)
.genThen([&]() { builder.createStoreWithConvert(loc, stat, statAddr); })
.end();
}
}

View File

@ -63,32 +63,20 @@ mlir::Value fir::runtime::genGetCommandArgument(
return builder.create<fir::CallOp>(loc, runtimeFunc, args).getResult(0);
}
mlir::Value fir::runtime::genEnvVariableValue(
fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value name,
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 fir::runtime::genGetEnvVariable(fir::FirOpBuilder &builder,
mlir::Location loc,
mlir::Value name, mlir::Value value,
mlir::Value length,
mlir::Value trimName,
mlir::Value errmsg) {
auto runtimeFunc =
fir::runtime::getRuntimeFunc<mkRTKey(GetEnvVariable)>(loc, builder);
mlir::FunctionType runtimeFuncTy = runtimeFunc.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::FunctionType lengthFuncTy = lengthFunc.getFunctionType();
mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc);
mlir::Value sourceLine =
fir::factory::locationToLineNo(builder, loc, lengthFuncTy.getInput(3));
fir::factory::locationToLineNo(builder, loc, runtimeFuncTy.getInput(6));
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);
builder, loc, runtimeFuncTy, name, value, length, trimName, errmsg,
sourceFile, sourceLine);
return builder.create<fir::CallOp>(loc, runtimeFunc, args).getResult(0);
}

View File

@ -226,45 +226,42 @@ static std::size_t LengthWithoutTrailingSpaces(const Descriptor &d) {
return s + 1;
}
static const char *GetEnvVariableValue(
const Descriptor &name, bool trim_name, const char *sourceFile, int line) {
std::size_t nameLength{
trim_name ? LengthWithoutTrailingSpaces(name) : name.ElementBytes()};
if (nameLength == 0) {
return nullptr;
}
std::int32_t RTNAME(GetEnvVariable)(const Descriptor &name,
const Descriptor *value, const Descriptor *length, bool trim_name,
const Descriptor *errmsg, const char *sourceFile, int line) {
Terminator terminator{sourceFile, line};
const char *value{executionEnvironment.GetEnv(
name.OffsetElement(), nameLength, terminator)};
return value;
}
std::int32_t RTNAME(EnvVariableValue)(const Descriptor &name,
const Descriptor *value, bool trim_name, const Descriptor *errmsg,
const char *sourceFile, int line) {
if (IsValidCharDescriptor(value)) {
if (value) {
RUNTIME_CHECK(terminator, IsValidCharDescriptor(value));
FillWithSpaces(*value);
}
const char *rawValue{GetEnvVariableValue(name, trim_name, sourceFile, line)};
// Store 0 in case we error out later on.
if (length) {
RUNTIME_CHECK(terminator, IsValidIntDescriptor(length));
StoreLengthToDescriptor(length, 0, terminator);
}
const char *rawValue{nullptr};
std::size_t nameLength{
trim_name ? LengthWithoutTrailingSpaces(name) : name.ElementBytes()};
if (nameLength != 0) {
rawValue = executionEnvironment.GetEnv(
name.OffsetElement(), nameLength, terminator);
}
if (!rawValue) {
return ToErrmsg(errmsg, StatMissingEnvVariable);
}
if (IsValidCharDescriptor(value)) {
return CopyToDescriptor(*value, rawValue, StringLength(rawValue), errmsg);
std::int64_t varLen{StringLength(rawValue)};
if (length && FitsInDescriptor(length, varLen, terminator)) {
StoreLengthToDescriptor(length, varLen, terminator);
}
if (value) {
return CopyToDescriptor(*value, rawValue, varLen, errmsg);
}
return StatOk;
}
std::int64_t RTNAME(EnvVariableLength)(
const Descriptor &name, bool trim_name, const char *sourceFile, int line) {
const char *value{GetEnvVariableValue(name, trim_name, sourceFile, line)};
if (!value) {
return 0;
}
return StringLength(value);
}
} // namespace Fortran::runtime

View File

@ -3,58 +3,54 @@
! 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)
! CHECK-SAME: %[[ARG_0:.*]]: !fir.boxchar<1> {fir.bindc_name = "name", fir.optional},
! CHECK-SAME: %[[ARG_1:.*]]: !fir.boxchar<1> {fir.bindc_name = "value", fir.optional},
! CHECK-SAME: %[[ARG_2:.*]]: !fir.ref<i32> {fir.bindc_name = "length", fir.optional},
! CHECK-SAME: %[[ARG_3:.*]]: !fir.ref<i32> {fir.bindc_name = "status", fir.optional},
! CHECK-SAME: %[[ARG_4:.*]]: !fir.ref<!fir.logical<4>> {fir.bindc_name = "trim_name", fir.optional},
! CHECK-SAME: %[[ARG_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
! Note: name is not optional in get_environment_variable and must be present
call get_environment_variable(name, value, length, status, trim_name, errmsg)
! CHECK: %[[VAL_0:.*]]:2 = fir.unboxchar %[[ARG_5]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
! CHECK: %[[VAL_1:.*]]:2 = fir.unboxchar %[[ARG_0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
! CHECK: %[[VAL_2:.*]]:2 = fir.unboxchar %[[ARG_1]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
! CHECK: %[[VAL_3:.*]] = fir.embox %[[VAL_1]]#0 typeparams %[[VAL_1]]#1 : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>>
! CHECK: %[[VAL_4:.*]] = fir.is_present %[[VAL_2]]#0 : (!fir.ref<!fir.char<1,?>>) -> i1
! CHECK: %[[VAL_5:.*]] = fir.embox %[[VAL_2]]#0 typeparams %[[VAL_2]]#1 : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>>
! CHECK: %[[VAL_6:.*]] = fir.absent !fir.box<!fir.char<1,?>>
! CHECK: %[[VAL_7:.*]] = arith.select %[[VAL_4]], %[[VAL_5]], %[[VAL_6]] : !fir.box<!fir.char<1,?>>
! CHECK: %[[VAL_8:.*]] = fir.is_present %[[ARG_2]] : (!fir.ref<i32>) -> i1
! CHECK: %[[VAL_9:.*]] = fir.embox %[[ARG_2]] : (!fir.ref<i32>) -> !fir.box<i32>
! CHECK: %[[VAL_10:.*]] = fir.absent !fir.box<i32>
! CHECK: %[[VAL_11:.*]] = arith.select %[[VAL_8]], %[[VAL_9]], %[[VAL_10]] : !fir.box<i32>
! CHECK: %[[VAL_12:.*]] = fir.is_present %[[VAL_0]]#0 : (!fir.ref<!fir.char<1,?>>) -> i1
! CHECK: %[[VAL_13:.*]] = fir.embox %[[VAL_0]]#0 typeparams %[[VAL_0]]#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 %[[ARG_4]] : (!fir.ref<!fir.logical<4>>) -> i64
! CHECK: %[[CONST_0:.*]] = arith.constant 0 : i64
! CHECK: %[[VAL_17:.*]] = arith.cmpi ne, %[[VAL_16]], %[[CONST_0]] : i64
! CHECK: %[[VAL_18:.*]] = fir.if %[[VAL_17]] -> (i1) {
! CHECK: %[[VAL_28:.*]] = fir.load %[[ARG_4]] : !fir.ref<!fir.logical<4>>
! CHECK: %[[VAL_29:.*]] = fir.convert %[[VAL_28]] : (!fir.logical<4>) -> i1
! CHECK: fir.result %[[VAL_29]] : i1
! CHECK: } else {
! CHECK: %[[VAL_24:.*]] = arith.constant true
! CHECK: fir.result %[[VAL_24]] : i1
! CHECK: %[[CONST_1:.*]] = arith.constant true
! CHECK: fir.result %[[CONST_1]] : 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: %[[VAL_20:.*]] = fir.convert %[[VAL_3]] : (!fir.box<!fir.char<1,?>>) -> !fir.box<none>
! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_7]] : (!fir.box<!fir.char<1,?>>) -> !fir.box<none>
! CHECK: %[[VAL_22:.*]] = fir.convert %[[VAL_11]] : (!fir.box<i32>) -> !fir.box<none>
! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_15]] : (!fir.box<!fir.char<1,?>>) -> !fir.box<none>
! CHECK: %[[VAL_25:.*]] = fir.call @_FortranAGetEnvVariable(%[[VAL_20]], %[[VAL_21]], %[[VAL_22]], %[[VAL_18]], %[[VAL_23]], %{{.*}}, %{{.*}}) {{.*}}: (!fir.box<none>, !fir.box<none>, !fir.box<none>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
! CHECK: %[[VAL_26:.*]] = fir.convert %[[ARG_3]] : (!fir.ref<i32>) -> i64
! CHECK: %[[CONST_2:.*]] = arith.constant 0 : i64
! CHECK: %[[VAL_27:.*]] = arith.cmpi ne, %[[VAL_26]], %[[CONST_2]] : i64
! CHECK: fir.if %[[VAL_27]] {
! CHECK: fir.store %[[VAL_25]] to %[[ARG_3]] : !fir.ref<i32>
! CHECK: }
end subroutine

View File

@ -1,15 +1,14 @@
! 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-LABEL: func @_QPname_only(
! CHECK-SAME: %[[nameArg:.*]]: !fir.boxchar<1> {fir.bindc_name = "name"}) {
subroutine number_only(name)
subroutine name_only(name)
character(len=32) :: name
call get_environment_variable(name)
! CHECK-NOT: fir.call @_FortranAEnvVariableValue
! CHECK-NOT: fir.call @_FortranAEnvVariableLength
! CHECK-NOT: fir.call @_FortranAGetEnvVariable
! CHECK-NEXT: return
end subroutine number_only
end subroutine name_only
! CHECK-LABEL: func @_QPname_and_value_only(
! CHECK-SAME: %[[nameArg:.*]]: !fir.boxchar<1> {fir.bindc_name = "name"},
@ -24,13 +23,14 @@ subroutine name_and_value_only(name, value)
! 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: %[[length:.*]] = 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 - 10]] : i32
! CHECK-NEXT: %[[sourceLine:.*]] = arith.constant [[# @LINE - 11]] : 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: %{{[0-9]+}} = fir.call @_FortranAGetEnvVariable(%[[name]], %[[value]], %[[length]], %true, %[[errmsg]], %[[sourceFile]], %[[sourceLine]]) {{.*}}: (!fir.box<none>, !fir.box<none>, !fir.box<none>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
! CHECK-NEXT: return
end subroutine name_and_value_only
@ -41,19 +41,19 @@ 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: %[[lengthBox:.*]] = fir.embox %arg1 : (!fir.ref<i[[DEFAULT_INTEGER_SIZE]]>) -> !fir.box<i[[DEFAULT_INTEGER_SIZE]]>
! CHECK-NEXT: %true = arith.constant true
! CHECK-NEXT: %[[value:.*]] = fir.absent !fir.box<none>
! CHECK-NEXT: %[[errmsg:.*]] = fir.absent !fir.box<none>
! CHECK: %[[sourceFileString:.*]] = fir.address_of(@_QQcl.{{.*}}) : !fir.ref<!fir.char<1,[[sourceFileLength:.*]]>>
! CHECK-NEXT: %[[sourceLine:.*]] = arith.constant [[# @LINE - 7]] : i32
! CHECK-NEXT: %[[sourceLine:.*]] = arith.constant [[# @LINE - 9]] : i32
! CHECK-NEXT: %[[name:.*]] = fir.convert %[[nameBox]] : (!fir.box<!fir.char<1,?>>) -> !fir.box<none>
! CHECK-NEXT: %[[length:.*]] = fir.convert %[[lengthBox]] : (!fir.box<i[[DEFAULT_INTEGER_SIZE]]>) -> !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: %{{.*}} = fir.call @_FortranAGetEnvVariable(%[[name]], %[[value]], %[[length]], %true, %[[errmsg]], %[[sourceFile]], %[[sourceLine]]) {{.*}}: (!fir.box<none>, !fir.box<none>, !fir.box<none>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
end subroutine name_and_length_only
! CHECK-LABEL: func @_QPname_and_status_only(
@ -68,13 +68,14 @@ subroutine name_and_status_only(name, status)
! CHECK-NEXT: %[[nameBox:.*]] = fir.embox %[[nameUnbox]]#0 typeparams %[[nameLength]] : (!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: %[[length:.*]] = 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: %[[sourceLine:.*]] = arith.constant [[# @LINE - 9]] : 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-32-NEXT: %[[status:.*]] = fir.call @_FortranAGetEnvVariable(%[[name]], %[[value]], %[[length]], %true, %[[errmsg]], %[[sourceFile]], %[[sourceLine]]) {{.*}}: (!fir.box<none>, !fir.box<none>, !fir.box<none>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
! CHECK-64-NEXT: %[[status32:.*]] = fir.call @_FortranAGetEnvVariable(%[[name]], %[[value]], %[[length]], %true, %[[errmsg]], %[[sourceFile]], %[[sourceLine]]) {{.*}}: (!fir.box<none>, !fir.box<none>, !fir.box<none>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
! 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
@ -86,8 +87,7 @@ 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-NOT: fir.call @_FortranAGetEnvVariable
! CHECK-NEXT: return
end subroutine name_and_trim_name_only
@ -105,12 +105,13 @@ subroutine name_and_errmsg_only(name, errmsg)
! 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: %[[length:.*]] = 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: %[[sourceLine:.*]] = arith.constant [[# @LINE - 11]] : 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: %{{[0-9]+}} = fir.call @_FortranAGetEnvVariable(%[[name]], %[[value]], %[[length]], %true, %[[errmsg]], %[[sourceFile]], %[[sourceLine]]) {{.*}}: (!fir.box<none>, !fir.box<none>, !fir.box<none>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
! CHECK-NEXT: return
end subroutine name_and_errmsg_only
@ -134,6 +135,7 @@ subroutine all_arguments(name, value, length, status, trim_name, errmsg)
! CHECK-NEXT: %[[valueLength:.*]] = arith.constant 32 : index
! 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: %[[lengthBoxed:.*]] = fir.embox %[[lengthArg]] : (!fir.ref<i[[DEFAULT_INTEGER_SIZE]]>) -> !fir.box<i[[DEFAULT_INTEGER_SIZE]]>
! CHECK-NEXT: %[[errmsgBoxed:.*]] = fir.embox %[[errmsgUnbox]]#0 typeparams %[[errmsgLength]] : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>>
! CHECK: %[[trimName:.*]] = fir.if %{{.*}} -> (i1) {
! CHECK-NEXT: %[[trimNameLoaded:.*]] = fir.load %[[trimNameArg]] : !fir.ref<!fir.logical<4>>
@ -144,21 +146,14 @@ subroutine all_arguments(name, value, length, status, trim_name, errmsg)
! 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: %[[sourceLine:.*]] = arith.constant [[# @LINE - 20]] : 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: %[[length:.*]] = fir.convert %[[lengthBoxed]] : (!fir.box<i[[DEFAULT_INTEGER_SIZE]]>) -> !fir.box<none>
! 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-32-NEXT: %[[status:.*]] = fir.call @_FortranAGetEnvVariable(%[[name]], %[[value]], %[[length]], %[[trimName]], %[[errmsg]], %[[sourceFile]], %[[sourceLine]]) {{.*}}: (!fir.box<none>, !fir.box<none>, !fir.box<none>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
! CHECK-64-NEXT: %[[status32:.*]] = fir.call @_FortranAGetEnvVariable(%[[name]], %[[value]], %[[length]], %[[trimName]], %[[errmsg]], %[[sourceFile]], %[[sourceLine]]) {{.*}}: (!fir.box<none>, !fir.box<none>, !fir.box<none>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
! 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: %[[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]]>
end subroutine all_arguments

View File

@ -26,11 +26,13 @@ void RTNAME(ProgramStart)(
int32_t RTNAME(ArgumentCount)();
int32_t RTNAME(GetCommandArgument)(int32_t, const struct Descriptor *,
const struct Descriptor *, const struct Descriptor *);
int32_t RTNAME(GetEnvVariable)();
int main() {
double x = RTNAME(CpuTime)();
RTNAME(ProgramStart)(0, 0, 0, 0);
int32_t c = RTNAME(ArgumentCount)();
int32_t v = RTNAME(GetCommandArgument)(0, 0, 0, 0);
return x + c + v;
int32_t e = RTNAME(GetEnvVariable)("FOO", 0, 0);
return x + c + v + e;
}

View File

@ -32,26 +32,15 @@ TEST_F(RuntimeCallTest, genGetCommandArgument) {
/*addLocArgs=*/true);
}
TEST_F(RuntimeCallTest, genEnvVariableValue) {
TEST_F(RuntimeCallTest, genGetEnvVariable) {
mlir::Location loc = firBuilder->getUnknownLoc();
mlir::Type charTy = fir::BoxType::get(firBuilder->getNoneType());
mlir::Value name = firBuilder->create<fir::UndefOp>(loc, charTy);
mlir::Value value = firBuilder->create<fir::UndefOp>(loc, charTy);
mlir::Value name = firBuilder->create<fir::UndefOp>(loc, boxTy);
mlir::Value value = firBuilder->create<fir::UndefOp>(loc, boxTy);
mlir::Value length = firBuilder->create<fir::UndefOp>(loc, boxTy);
mlir::Value trimName = firBuilder->create<fir::UndefOp>(loc, i1Ty);
mlir::Value errmsg = firBuilder->create<fir::UndefOp>(loc, charTy);
mlir::Value result = fir::runtime::genEnvVariableValue(
*firBuilder, loc, name, value, trimName, errmsg);
checkCallOp(result.getDefiningOp(), "_FortranAEnvVariableValue", /*nbArgs=*/4,
mlir::Value errmsg = firBuilder->create<fir::UndefOp>(loc, boxTy);
mlir::Value result = fir::runtime::genGetEnvVariable(
*firBuilder, loc, name, value, length, trimName, errmsg);
checkCallOp(result.getDefiningOp(), "_FortranAGetEnvVariable", /*nbArgs=*/5,
/*addLocArgs=*/true);
}
TEST_F(RuntimeCallTest, genEnvVariableLength) {
mlir::Location loc = firBuilder->getUnknownLoc();
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);
}

View File

@ -132,12 +132,12 @@ protected:
SCOPED_TRACE(name);
SCOPED_TRACE("Checking environment variable");
CheckValue(
[&](const Descriptor *value, const Descriptor *,
[&](const Descriptor *value, const Descriptor *length,
const Descriptor *errmsg) {
return RTNAME(EnvVariableValue)(*CharDescriptor(name), value,
trimName, errmsg, /*sourceFile=*/nullptr, /*line=*/0);
return RTNAME(GetEnvVariable)(
*CharDescriptor(name), value, length, trimName, errmsg);
},
expectedValue);
expectedValue, std::strlen(expectedValue));
}
void CheckMissingEnvVarValue(const char *name, bool trimName = true) const {
@ -147,15 +147,13 @@ protected:
ASSERT_EQ(nullptr, std::getenv(name))
<< "Environment variable " << name << " not expected to exist";
OwningPtr<Descriptor> nameDescriptor{CharDescriptor(name)};
EXPECT_EQ(0, RTNAME(EnvVariableLength)(*nameDescriptor, trimName));
CheckValue(
[&](const Descriptor *value, const Descriptor *,
[&](const Descriptor *value, const Descriptor *length,
const Descriptor *errmsg) {
return RTNAME(EnvVariableValue)(*nameDescriptor, value, trimName,
errmsg, /*sourceFile=*/nullptr, /*line=*/0);
return RTNAME(GetEnvVariable)(
*CharDescriptor(name), value, length, trimName, errmsg);
},
"", -1, 1, "Missing environment variable");
"", 0, 1, "Missing environment variable");
}
void CheckMissingArgumentValue(int n, const char *errStr = nullptr) const {
@ -416,7 +414,6 @@ private:
TEST_F(EnvironmentVariables, Nonexistent) {
CheckMissingEnvVarValue("DOESNT_EXIST");
CheckMissingEnvVarValue(" ");
CheckMissingEnvVarValue("");
}
@ -425,12 +422,15 @@ TEST_F(EnvironmentVariables, Basic) {
// Test a variable that's expected to exist in the environment.
char *path{std::getenv("PATH")};
auto expectedLen{static_cast<int64_t>(std::strlen(path))};
EXPECT_EQ(expectedLen, RTNAME(EnvVariableLength)(*CharDescriptor("PATH")));
OwningPtr<Descriptor> length{EmptyIntDescriptor()};
EXPECT_EQ(0,
RTNAME(GetEnvVariable)(*CharDescriptor("PATH"),
/*value=*/nullptr, length.get()));
CheckDescriptorEqInt(length.get(), expectedLen);
}
TEST_F(EnvironmentVariables, Trim) {
if (EnableFineGrainedTests()) {
EXPECT_EQ(5, RTNAME(EnvVariableLength)(*CharDescriptor("NAME ")));
CheckEnvVarValue("VALUE", "NAME ");
}
}
@ -443,7 +443,6 @@ TEST_F(EnvironmentVariables, NoTrim) {
TEST_F(EnvironmentVariables, Empty) {
if (EnableFineGrainedTests()) {
EXPECT_EQ(0, RTNAME(EnvVariableLength)(*CharDescriptor("EMPTY")));
CheckEnvVarValue("", "EMPTY");
}
}
@ -451,10 +450,10 @@ TEST_F(EnvironmentVariables, Empty) {
TEST_F(EnvironmentVariables, NoValueOrErrmsg) {
ASSERT_EQ(std::getenv("DOESNT_EXIST"), nullptr)
<< "Environment variable DOESNT_EXIST actually exists";
EXPECT_EQ(RTNAME(EnvVariableValue)(*CharDescriptor("DOESNT_EXIST")), 1);
EXPECT_EQ(RTNAME(GetEnvVariable)(*CharDescriptor("DOESNT_EXIST")), 1);
if (EnableFineGrainedTests()) {
EXPECT_EQ(RTNAME(EnvVariableValue)(*CharDescriptor("NAME")), 0);
EXPECT_EQ(RTNAME(GetEnvVariable)(*CharDescriptor("NAME")), 0);
}
}
@ -462,16 +461,16 @@ TEST_F(EnvironmentVariables, ValueTooShort) {
if (EnableFineGrainedTests()) {
OwningPtr<Descriptor> tooShort{CreateEmptyCharDescriptor<2>()};
ASSERT_NE(tooShort, nullptr);
EXPECT_EQ(RTNAME(EnvVariableValue)(*CharDescriptor("NAME"), tooShort.get(),
/*trim_name=*/true, nullptr),
EXPECT_EQ(RTNAME(GetEnvVariable)(*CharDescriptor("NAME"), tooShort.get(),
/*length=*/nullptr, /*trim_name=*/true, nullptr),
-1);
CheckDescriptorEqStr(tooShort.get(), "VALUE");
OwningPtr<Descriptor> errMsg{CreateEmptyCharDescriptor()};
ASSERT_NE(errMsg, nullptr);
EXPECT_EQ(RTNAME(EnvVariableValue)(*CharDescriptor("NAME"), tooShort.get(),
/*trim_name=*/true, errMsg.get()),
EXPECT_EQ(RTNAME(GetEnvVariable)(*CharDescriptor("NAME"), tooShort.get(),
/*length=*/nullptr, /*trim_name=*/true, errMsg.get()),
-1);
std::string expectedErrMsg{
@ -485,8 +484,8 @@ TEST_F(EnvironmentVariables, ErrMsgTooShort) {
<< "Environment variable DOESNT_EXIST actually exists";
OwningPtr<Descriptor> errMsg{CreateEmptyCharDescriptor<3>()};
EXPECT_EQ(RTNAME(EnvVariableValue)(*CharDescriptor("DOESNT_EXIST"), nullptr,
/*trim_name=*/true, errMsg.get()),
EXPECT_EQ(RTNAME(GetEnvVariable)(*CharDescriptor("DOESNT_EXIST"), nullptr,
/*length=*/nullptr, /*trim_name=*/true, errMsg.get()),
1);
CheckDescriptorEqStr(errMsg.get(), "Mis");
}