Skip to content

Commit e1ad273

Browse files
authored
[flang] Clean up ISO_FORTRAN_ENV, fix NUMERIC_STORAGE_SIZE (#87566)
Address TODOs in the intrinsic module ISO_FORTRAN_ENV, and extend the implementation of NUMERIC_STORAGE_SIZE so that the calculation of its value is deferred until it is needed so that the effects of -fdefault-integer-8 or -fdefault-real-8 are reflected. Emit a warning when NUMERIC_STORAGE_SIZE is used from the module file and the default integer and real sizes do not match. Fixes #87476.
1 parent 97e3f60 commit e1ad273

File tree

10 files changed

+129
-65
lines changed

10 files changed

+129
-65
lines changed

flang/include/flang/Evaluate/common.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -256,9 +256,11 @@ class FoldingContext {
256256
const common::LanguageFeatureControl &languageFeatures() const {
257257
return languageFeatures_;
258258
}
259-
bool inModuleFile() const { return inModuleFile_; }
260-
FoldingContext &set_inModuleFile(bool yes = true) {
261-
inModuleFile_ = yes;
259+
std::optional<parser::CharBlock> moduleFileName() const {
260+
return moduleFileName_;
261+
}
262+
FoldingContext &set_moduleFileName(std::optional<parser::CharBlock> n) {
263+
moduleFileName_ = n;
262264
return *this;
263265
}
264266

@@ -288,7 +290,7 @@ class FoldingContext {
288290
const IntrinsicProcTable &intrinsics_;
289291
const TargetCharacteristics &targetCharacteristics_;
290292
const semantics::DerivedTypeSpec *pdtInstance_{nullptr};
291-
bool inModuleFile_{false};
293+
std::optional<parser::CharBlock> moduleFileName_;
292294
std::map<parser::CharBlock, ConstantSubscript> impliedDos_;
293295
const common::LanguageFeatureControl &languageFeatures_;
294296
std::set<std::string> &tempNames_;

flang/lib/Evaluate/check-expression.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,14 @@ std::optional<Expr<SomeType>> NonPointerInitializationExpr(const Symbol &symbol,
478478
return {std::move(folded)};
479479
}
480480
} else if (IsNamedConstant(symbol)) {
481+
if (symbol.name() == "numeric_storage_size" &&
482+
symbol.owner().IsModule() &&
483+
DEREF(symbol.owner().symbol()).name() == "iso_fortran_env") {
484+
// Very special case: numeric_storage_size is not folded until
485+
// it read from the iso_fortran_env module file, as its value
486+
// depends on compilation options.
487+
return {std::move(folded)};
488+
}
481489
context.messages().Say(
482490
"Value of named constant '%s' (%s) cannot be computed as a constant value"_err_en_US,
483491
symbol.name(), folded.AsFortran());

flang/lib/Evaluate/fold-implementation.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1969,7 +1969,7 @@ Expr<T> FoldOperation(FoldingContext &context, Divide<T> &&x) {
19691969
// NaN, and Inf respectively.
19701970
bool isCanonicalNaNOrInf{false};
19711971
if constexpr (T::category == TypeCategory::Real) {
1972-
if (folded->second.IsZero() && context.inModuleFile()) {
1972+
if (folded->second.IsZero() && context.moduleFileName().has_value()) {
19731973
using IntType = typename T::Scalar::Word;
19741974
auto intNumerator{folded->first.template ToInteger<IntType>()};
19751975
isCanonicalNaNOrInf = intNumerator.flags == RealFlags{} &&

flang/lib/Evaluate/fold-integer.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1302,6 +1302,24 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
13021302
return FoldSum<T>(context, std::move(funcRef));
13031303
} else if (name == "ubound") {
13041304
return UBOUND(context, std::move(funcRef));
1305+
} else if (name == "__builtin_numeric_storage_size") {
1306+
if (!context.moduleFileName()) {
1307+
// Don't fold this reference until it appears in the module file
1308+
// for ISO_FORTRAN_ENV -- the value depends on the compiler options
1309+
// that might be in force.
1310+
} else {
1311+
auto intBytes{
1312+
context.targetCharacteristics().GetByteSize(TypeCategory::Integer,
1313+
context.defaults().GetDefaultKind(TypeCategory::Integer))};
1314+
auto realBytes{
1315+
context.targetCharacteristics().GetByteSize(TypeCategory::Real,
1316+
context.defaults().GetDefaultKind(TypeCategory::Real))};
1317+
if (intBytes != realBytes) {
1318+
context.messages().Say(*context.moduleFileName(),
1319+
"NUMERIC_STORAGE_SIZE from ISO_FORTRAN_ENV is not well-defined when default INTEGER and REAL are not consistent due to compiler options"_warn_en_US);
1320+
}
1321+
return Expr<T>{8 * std::min(intBytes, realBytes)};
1322+
}
13051323
}
13061324
return Expr<T>{std::move(funcRef)};
13071325
}

flang/lib/Evaluate/intrinsics.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -903,6 +903,8 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
903903
{"back", AnyLogical, Rank::elemental, Optionality::optional},
904904
DefaultingKIND},
905905
KINDInt},
906+
{"__builtin_compiler_options", {}, DefaultChar},
907+
{"__builtin_compiler_version", {}, DefaultChar},
906908
{"__builtin_fma", {{"f1", SameReal}, {"f2", SameReal}, {"f3", SameReal}},
907909
SameReal},
908910
{"__builtin_ieee_is_nan", {{"a", AnyFloating}}, DefaultLogical},
@@ -941,8 +943,7 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
941943
{"__builtin_ieee_support_underflow_control",
942944
{{"x", AnyReal, Rank::elemental, Optionality::optional}},
943945
DefaultLogical},
944-
{"__builtin_compiler_options", {}, DefaultChar},
945-
{"__builtin_compiler_version", {}, DefaultChar},
946+
{"__builtin_numeric_storage_size", {}, DefaultInt},
946947
};
947948

948949
// TODO: Coarray intrinsic functions

flang/lib/Semantics/mod-file.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1458,11 +1458,11 @@ Scope *ModFileReader::Read(SourceName name, std::optional<bool> isIntrinsic,
14581458
parentScope = ancestor;
14591459
}
14601460
// Process declarations from the module file
1461-
bool wasInModuleFile{context_.foldingContext().inModuleFile()};
1462-
context_.foldingContext().set_inModuleFile(true);
1461+
auto wasModuleFileName{context_.foldingContext().moduleFileName()};
1462+
context_.foldingContext().set_moduleFileName(name);
14631463
GetModuleDependences(context_.moduleDependences(), sourceFile->content());
14641464
ResolveNames(context_, parseTree, topScope);
1465-
context_.foldingContext().set_inModuleFile(wasInModuleFile);
1465+
context_.foldingContext().set_moduleFileName(wasModuleFileName);
14661466
if (!moduleSymbol) {
14671467
// Submodule symbols' storage are owned by their parents' scopes,
14681468
// but their names are not in their parents' dictionaries -- we

flang/lib/Semantics/resolve-names.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,9 @@ class BaseVisitor {
175175
}
176176
}
177177

178-
bool InModuleFile() const { return GetFoldingContext().inModuleFile(); }
178+
bool InModuleFile() const {
179+
return GetFoldingContext().moduleFileName().has_value();
180+
}
179181

180182
// Make a placeholder symbol for a Name that otherwise wouldn't have one.
181183
// It is not in any scope and always has MiscDetails.

flang/module/iso_fortran_env.f90

Lines changed: 41 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@
66
!
77
!===------------------------------------------------------------------------===!
88

9-
! See Fortran 2018, clause 16.10.2
10-
! TODO: These are placeholder values so that some tests can be run.
9+
! See Fortran 2023, subclause 16.10.2
1110

1211
include '../include/flang/Runtime/magic-numbers.h'
1312

@@ -24,27 +23,20 @@ module iso_fortran_env
2423
compiler_version => __builtin_compiler_version
2524

2625
implicit none
27-
28-
! Set PRIVATE by default to explicitly only export what is meant
29-
! to be exported by this MODULE.
3026
private
3127

3228
public :: event_type, notify_type, lock_type, team_type, &
3329
atomic_int_kind, atomic_logical_kind, compiler_options, &
3430
compiler_version
3531

36-
37-
! TODO: Use PACK([x],test) in place of the array constructor idiom
38-
! [(x, integer::j=1,COUNT([test]))] below once PACK() can be folded.
39-
4032
integer, parameter :: &
4133
selectedASCII = selected_char_kind('ASCII'), &
4234
selectedUCS_2 = selected_char_kind('UCS-2'), &
4335
selectedUnicode = selected_char_kind('ISO_10646')
4436
integer, parameter, public :: character_kinds(*) = [ &
45-
[(selectedASCII, integer :: j=1, count([selectedASCII >= 0]))], &
46-
[(selectedUCS_2, integer :: j=1, count([selectedUCS_2 >= 0]))], &
47-
[(selectedUnicode, integer :: j=1, count([selectedUnicode >= 0]))]]
37+
pack([selectedASCII], selectedASCII >= 0), &
38+
pack([selectedUCS_2], selectedUCS_2 >= 0), &
39+
pack([selectedUnicode], selectedUnicode >= 0)]
4840

4941
integer, parameter :: &
5042
selectedInt8 = selected_int_kind(2), &
@@ -76,19 +68,18 @@ module iso_fortran_env
7668

7769
integer, parameter, public :: integer_kinds(*) = [ &
7870
selected_int_kind(0), &
79-
((selected_int_kind(k), &
80-
integer :: j=1, count([selected_int_kind(k) >= 0 .and. &
81-
selected_int_kind(k) /= &
82-
selected_int_kind(k-1)])), &
83-
integer :: k=1, 39)]
71+
[(pack([selected_int_kind(k)], &
72+
selected_int_kind(k) >= 0 .and. &
73+
selected_int_kind(k) /= selected_int_kind(k-1)), &
74+
integer :: k=1, 39)]]
8475

8576
integer, parameter, public :: &
8677
logical8 = int8, logical16 = int16, logical32 = int32, logical64 = int64
8778
integer, parameter, public :: logical_kinds(*) = [ &
88-
[(logical8, integer :: j=1, count([logical8 >= 0]))], &
89-
[(logical16, integer :: j=1, count([logical16 >= 0]))], &
90-
[(logical32, integer :: j=1, count([logical32 >= 0]))], &
91-
[(logical64, integer :: j=1, count([logical64 >= 0]))]]
79+
pack([logical8], logical8 >= 0), &
80+
pack([logical16], logical16 >= 0), &
81+
pack([logical32], logical32 >= 0), &
82+
pack([logical64], logical64 >= 0)]
9283

9384
integer, parameter :: &
9485
selectedReal16 = selected_real_kind(3, 4), & ! IEEE half
@@ -129,35 +120,40 @@ module iso_fortran_env
129120
digits(real(0,kind=safeReal128)) == 113)
130121

131122
integer, parameter, public :: real_kinds(*) = [ &
132-
[(real16, integer :: j=1, count([real16 >= 0]))], &
133-
[(bfloat16, integer :: j=1, count([bfloat16 >= 0]))], &
134-
[(real32, integer :: j=1, count([real32 >= 0]))], &
135-
[(real64, integer :: j=1, count([real64 >= 0]))], &
136-
[(real80, integer :: j=1, count([real80 >= 0]))], &
137-
[(real64x2, integer :: j=1, count([real64x2 >= 0]))], &
138-
[(real128, integer :: j=1, count([real128 >= 0]))]]
139-
140-
integer, parameter, public :: current_team = -1, initial_team = -2, parent_team = -3
141-
142-
integer, parameter, public :: output_unit = FORTRAN_DEFAULT_OUTPUT_UNIT
143-
integer, parameter, public :: input_unit = FORTRAN_DEFAULT_INPUT_UNIT
144-
integer, parameter, public :: error_unit = FORTRAN_ERROR_UNIT
145-
integer, parameter, public :: iostat_end = FORTRAN_RUNTIME_IOSTAT_END
146-
integer, parameter, public :: iostat_eor = FORTRAN_RUNTIME_IOSTAT_EOR
147-
integer, parameter, public :: iostat_inquire_internal_unit = &
148-
FORTRAN_RUNTIME_IOSTAT_INQUIRE_INTERNAL_UNIT
123+
pack([real16], real16 >= 0), &
124+
pack([bfloat16], bfloat16 >= 0), &
125+
pack([real32], real32 >= 0), &
126+
pack([real64], real64 >= 0), &
127+
pack([real80], real80 >= 0), &
128+
pack([real64x2], real64x2 >= 0), &
129+
pack([real128], real128 >= 0)]
130+
131+
integer, parameter, public :: current_team = -1, &
132+
initial_team = -2, &
133+
parent_team = -3
149134

150135
integer, parameter, public :: character_storage_size = 8
151136
integer, parameter, public :: file_storage_size = 8
152-
integer, parameter, public :: numeric_storage_size = 32
153137

154-
integer, parameter, public :: stat_failed_image = FORTRAN_RUNTIME_STAT_FAILED_IMAGE
155-
integer, parameter, public :: stat_locked = FORTRAN_RUNTIME_STAT_LOCKED
156-
integer, parameter, public :: &
157-
stat_locked_other_image = FORTRAN_RUNTIME_STAT_LOCKED_OTHER_IMAGE
158-
integer, parameter, public :: stat_stopped_image = FORTRAN_RUNTIME_STAT_STOPPED_IMAGE
159-
integer, parameter, public :: stat_unlocked = FORTRAN_RUNTIME_STAT_UNLOCKED
138+
intrinsic :: __builtin_numeric_storage_size
139+
! This value depends on any -fdefault-integer-N and -fdefault-real-N
140+
! compiler options that are active when the module file is read.
141+
integer, parameter, public :: numeric_storage_size = &
142+
__builtin_numeric_storage_size()
143+
144+
! From Runtime/magic-numbers.h:
160145
integer, parameter, public :: &
146+
output_unit = FORTRAN_DEFAULT_OUTPUT_UNIT, &
147+
input_unit = FORTRAN_DEFAULT_INPUT_UNIT, &
148+
error_unit = FORTRAN_ERROR_UNIT, &
149+
iostat_end = FORTRAN_RUNTIME_IOSTAT_END, &
150+
iostat_eor = FORTRAN_RUNTIME_IOSTAT_EOR, &
151+
iostat_inquire_internal_unit = FORTRAN_RUNTIME_IOSTAT_INQUIRE_INTERNAL_UNIT, &
152+
stat_failed_image = FORTRAN_RUNTIME_STAT_FAILED_IMAGE, &
153+
stat_locked = FORTRAN_RUNTIME_STAT_LOCKED, &
154+
stat_locked_other_image = FORTRAN_RUNTIME_STAT_LOCKED_OTHER_IMAGE, &
155+
stat_stopped_image = FORTRAN_RUNTIME_STAT_STOPPED_IMAGE, &
156+
stat_unlocked = FORTRAN_RUNTIME_STAT_UNLOCKED, &
161157
stat_unlocked_failed_image = FORTRAN_RUNTIME_STAT_UNLOCKED_FAILED_IMAGE
162158

163159
end module iso_fortran_env
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
! RUN: %flang_fc1 -fdebug-unparse %s 2>&1 | FileCheck %s --check-prefix=CHECK
2+
! RUN: %flang_fc1 -fdebug-unparse -fdefault-integer-8 %s 2>&1 | FileCheck %s --check-prefix=CHECK-I8
3+
! RUN: %flang_fc1 -fdebug-unparse %s -fdefault-real-8 2>&1 | FileCheck %s --check-prefix=CHECK-R8
4+
! RUN: %flang_fc1 -fdebug-unparse %s -fdefault-integer-8 -fdefault-real-8 2>&1 | FileCheck %s --check-prefix=CHECK-I8-R8
5+
6+
use iso_fortran_env
7+
8+
!CHECK-NOT: warning
9+
!CHECK: nss = 32_4
10+
!CHECK-I8: warning: NUMERIC_STORAGE_SIZE from ISO_FORTRAN_ENV is not well-defined when default INTEGER and REAL are not consistent due to compiler options
11+
!CHECK-I8: nss = 32_4
12+
!CHECK-R8: warning: NUMERIC_STORAGE_SIZE from ISO_FORTRAN_ENV is not well-defined when default INTEGER and REAL are not consistent due to compiler options
13+
!CHECK-R8: nss = 32_4
14+
!CHECK-I8-R8: nss = 64_4
15+
integer, parameter :: nss = numeric_storage_size
16+
17+
!CHECK: iss = 32_4
18+
!CHECK-I8: iss = 64_8
19+
!CHECK-R8: iss = 32_4
20+
!CHECK-I8-R8: iss = 64_8
21+
integer, parameter :: iss = storage_size(1)
22+
23+
!CHECK: rss = 32_4
24+
!CHECK-I8: rss = 32_8
25+
!CHECK-R8: rss = 64_4
26+
!CHECK-I8-R8: rss = 64_8
27+
integer, parameter :: rss = storage_size(1.)
28+
29+
!CHECK: zss = 64_4
30+
!CHECK-I8: zss = 64_8
31+
!CHECK-R8: zss = 128_4
32+
!CHECK-I8-R8: zss = 128_8
33+
integer, parameter :: zss = storage_size((1.,0.))
34+
35+
!CHECK: lss = 32_4
36+
!CHECK-I8: lss = 64_8
37+
!CHECK-R8: lss = 32_4
38+
!CHECK-I8-R8: lss = 64_8
39+
integer, parameter :: lss = storage_size(.true.)
40+
end

flang/tools/f18/CMakeLists.txt

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@ set(MODULES
1717
"ieee_features"
1818
"iso_c_binding"
1919
"iso_fortran_env"
20-
"__fortran_builtins"
21-
"__fortran_type_info"
2220
)
2321

2422
# Create module files directly from the top-level module source directory.
@@ -27,22 +25,20 @@ set(MODULES
2725
# can't be used for generating module files.
2826
if (NOT CMAKE_CROSSCOMPILING)
2927
foreach(filename ${MODULES})
30-
set(base ${FLANG_INTRINSIC_MODULES_DIR}/${filename})
31-
if(${filename} STREQUAL "__fortran_builtins")
32-
set(depends "")
33-
elseif(${filename} STREQUAL "__ppc_types")
34-
set(depends "")
28+
set(depends "")
29+
if(${filename} STREQUAL "__fortran_builtins" OR
30+
${filename} STREQUAL "__ppc_types")
3531
elseif(${filename} STREQUAL "__ppc_intrinsics" OR
3632
${filename} STREQUAL "mma")
3733
set(depends ${FLANG_INTRINSIC_MODULES_DIR}/__ppc_types.mod)
3834
else()
3935
set(depends ${FLANG_INTRINSIC_MODULES_DIR}/__fortran_builtins.mod)
4036
if(NOT ${filename} STREQUAL "__fortran_type_info")
41-
set(depends ${FLANG_INTRINSIC_MODULES_DIR}/__fortran_type_info.mod)
37+
set(depends ${depends} ${FLANG_INTRINSIC_MODULES_DIR}/__fortran_type_info.mod)
4238
endif()
4339
if(${filename} STREQUAL "ieee_arithmetic" OR
4440
${filename} STREQUAL "ieee_exceptions")
45-
set(depends ${FLANG_INTRINSIC_MODULES_DIR}/__fortran_ieee_exceptions.mod)
41+
set(depends ${depends} ${FLANG_INTRINSIC_MODULES_DIR}/__fortran_ieee_exceptions.mod)
4642
endif()
4743
endif()
4844

@@ -58,6 +54,7 @@ if (NOT CMAKE_CROSSCOMPILING)
5854
endif()
5955
endif()
6056

57+
set(base ${FLANG_INTRINSIC_MODULES_DIR}/${filename})
6158
# TODO: We may need to flag this with conditional, in case Flang is built w/o OpenMP support
6259
add_custom_command(OUTPUT ${base}.mod
6360
COMMAND ${CMAKE_COMMAND} -E make_directory ${FLANG_INTRINSIC_MODULES_DIR}

0 commit comments

Comments
 (0)