[flang-commits] [flang] 6eefadd - [flang][Semantics] Ensure deterministic mod file output (#129669)
via flang-commits
flang-commits at lists.llvm.org
Tue Mar 4 23:27:21 PST 2025
Author: IƱaki Amatria Barral
Date: 2025-03-05T08:27:17+01:00
New Revision: 6eefadd8efc0584211cb5283e0acc00a45588242
URL: https://github.com/llvm/llvm-project/commit/6eefadd8efc0584211cb5283e0acc00a45588242
DIFF: https://github.com/llvm/llvm-project/commit/6eefadd8efc0584211cb5283e0acc00a45588242.diff
LOG: [flang][Semantics] Ensure deterministic mod file output (#129669)
This PR is a follow-up to #128655.
It adds another test to ensure deterministic ordering in `.mod` files
and includes related changes to prevent non-deterministic ordering
caused by iterating over a set ordered by heap pointers. This issue is
particularly noticeable when using Flang as a library and compiling the
same files multiple times.
The reduced test case is as minimal as possible. We were unable to
reproduce the issue with a smaller set of files.
Added:
flang/test/Semantics/Inputs/modfile73-a.f90
flang/test/Semantics/Inputs/modfile73-b.f90
flang/test/Semantics/Inputs/modfile73-c.f90
flang/test/Semantics/modfile73.f90
Modified:
flang/lib/Semantics/mod-file.cpp
Removed:
################################################################################
diff --git a/flang/lib/Semantics/mod-file.cpp b/flang/lib/Semantics/mod-file.cpp
index 1dfd9c35b3f43..ac176978a45a5 100644
--- a/flang/lib/Semantics/mod-file.cpp
+++ b/flang/lib/Semantics/mod-file.cpp
@@ -47,7 +47,7 @@ struct ModHeader {
static std::optional<SourceName> GetSubmoduleParent(const parser::Program &);
static void CollectSymbols(
- const Scope &, SymbolVector &, SymbolVector &, UnorderedSymbolSet &);
+ const Scope &, SymbolVector &, SymbolVector &, SourceOrderedSymbolSet &);
static void PutPassName(llvm::raw_ostream &, const std::optional<SourceName> &);
static void PutInit(llvm::raw_ostream &, const Symbol &, const MaybeExpr &,
const parser::Expr *);
@@ -363,7 +363,7 @@ void ModFileWriter::PutSymbols(
auto &renamings{context_.moduleFileOutputRenamings()};
auto previousRenamings{std::move(renamings)};
PrepareRenamings(scope);
- UnorderedSymbolSet modules;
+ SourceOrderedSymbolSet modules;
CollectSymbols(scope, sorted, uses, modules);
// Write module files for dependencies first so that their
// hashes are known.
@@ -839,7 +839,7 @@ void ModFileWriter::PutUseExtraAttr(
// Collect the symbols of this scope sorted by their original order, not name.
// Generics and namelists are exceptions: they are sorted after other symbols.
void CollectSymbols(const Scope &scope, SymbolVector &sorted,
- SymbolVector &uses, UnorderedSymbolSet &modules) {
+ SymbolVector &uses, SourceOrderedSymbolSet &modules) {
SymbolVector namelist, generics;
auto symbols{scope.GetSymbols()};
std::size_t commonSize{scope.commonBlocks().size()};
diff --git a/flang/test/Semantics/Inputs/modfile73-a.f90 b/flang/test/Semantics/Inputs/modfile73-a.f90
new file mode 100644
index 0000000000000..45a93f6c1b097
--- /dev/null
+++ b/flang/test/Semantics/Inputs/modfile73-a.f90
@@ -0,0 +1,197 @@
+MODULE modfile73a
+PUBLIC re_alloc, defaults
+integersp
+integerselected_real_kind0
+integer:: i8b = selected_int_kind(8)
+interface
+ subroutine alloc_error_report_interf(str,code)
+ end
+ subroutine alloc_memory_event_interf(bytes,name)
+ end
+end interface
+procedure()alloc_error_report
+procedure()alloc_memory_event
+ interface de_alloc
+ end interface
+ charactercharacter, DEFAULT_ROUTINE
+ type allocDefaults
+ logical copy
+ logical shrink
+ integer imin
+ characterroutine
+ end type
+ type(allocDefaults)DEFAULT
+ integer IERR
+ logical ASSOCIATED_ARRAY, NEEDS_ALLOC, NEEDS_COPY, NEEDS_DEALLOC
+CONTAINS
+ subroutine set_alloc_event_handler(func)
+ end
+ subroutine set_alloc_error_handler(func)
+ end
+ subroutine dummy_alloc_memory_event(bytes,name)
+ end
+ subroutine dummy_alloc_error_report(name,code)
+ end
+SUBROUTINE alloc_default( old, new, restore, routine, copy, shrink, imin )
+END
+SUBROUTINE realloc_i1( array, i1min, i1max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_i2( array, i1min,i1max, i2min,i2max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_i3( array, i1min,i1max, i2min,i2max, i3min,i3max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_i4( array, i1min,i1max, i2min,i2max, i3min,i3max, i4min,i4max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_i5( array, i1min,i1max, i2min,i2max, i3min,i3max, i4min, i4max, i5min, i5max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_E1( array, i1min, i1max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_r1( array, i1min, i1max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_r2( array, i1min,i1max, i2min,i2max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_r3( array, i1min,i1max, i2min,i2max, i3min,i3max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_r4( array, i1min,i1max, i2min,i2max, i3min,i3max, i4min,i4max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_r5( array, i1min,i1max, i2min,i2max, i3min,i3max, i4min, i4max, i5min, i5max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_d1( array, i1min, i1max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_d2( array, i1min,i1max, i2min,i2max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_d3( array, i1min,i1max, i2min,i2max, i3min,i3max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_d4( array, i1min,i1max, i2min,i2max, i3min,i3max, i4min,i4max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_d5( array, i1min,i1max, i2min,i2max, i3min,i3max, i4min,i4max, i5min,i5max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_c1( array, i1min, i1max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_c2( array, i1min,i1max, i2min,i2max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_c3( array, i1min,i1max, i2min,i2max, i3min,i3max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_c4( array, i1min,i1max, i2min,i2max, i3min,i3max, i4min,i4max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_c5( array, i1min,i1max, i2min,i2max, i3min,i3max, i4min, i4max, i5min, i5max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_z1( array, i1min, i1max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_z2( array, i1min,i1max, i2min,i2max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_z3( array, i1min,i1max, i2min,i2max, i3min,i3max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_z4( array, i1min,i1max, i2min,i2max, i3min,i3max, i4min,i4max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_z5( array, i1min,i1max, i2min,i2max, i3min,i3max, i4min, i4max, i5min, i5max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_l1( array, i1min,i1max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_l2( array, i1min,i1max, i2min,i2max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_l3( array, i1min,i1max, i2min,i2max, i3min,i3max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_l4( array, i1min,i1max, i2min,i2max, i3min,i3max, i4min,i4max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_l5( array, i1min,i1max, i2min,i2max, i3min,i3max, i4min, i4max, i5min, i5max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_i1s( array, i1max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_i2s( array, i1max, i2max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_i3s( array, i1max, i2max, i3max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_r1s( array, i1max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_r2s( array, i1max, i2max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_r3s( array, i1max, i2max, i3max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_r4s( array, i1max, i2max, i3max, i4max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_d1s( array, i1max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_d3s( array, i1max, i2max, i3max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_d4s( array, i1max, i2max, i3max, i4max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_l1s( array, i1max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_l2s( array, i1max, i2max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_l3s( array, i1max, i2max, i3max, name, routine, copy, shrink )
+END
+SUBROUTINE realloc_s1( array, i1min, i1max, name, routine, copy, shrink )
+END
+SUBROUTINE dealloc_i1( array, name, routine )
+END
+SUBROUTINE dealloc_i2( array, name, routine )
+END
+SUBROUTINE dealloc_i3( array, name, routine )
+END
+SUBROUTINE dealloc_i4( array, name, routine )
+ END
+SUBROUTINE dealloc_i5( array, name, routine )
+ END
+SUBROUTINE dealloc_E1( array, name, routine )
+END
+SUBROUTINE dealloc_r1( array, name, routine )
+END
+SUBROUTINE dealloc_r2( array, name, routine )
+END
+SUBROUTINE dealloc_r3( array, name, routine )
+END
+SUBROUTINE dealloc_r4( array, name, routine )
+END
+SUBROUTINE dealloc_r5( array, name, routine )
+END
+SUBROUTINE dealloc_d1( array, name, routine )
+END
+SUBROUTINE dealloc_d2( array, name, routine )
+END
+SUBROUTINE dealloc_d3( array, name, routine )
+END
+SUBROUTINE dealloc_d4( array, name, routine )
+END
+SUBROUTINE dealloc_d5( array, name, routine )
+END
+SUBROUTINE dealloc_c1( array, name, routine )
+END
+SUBROUTINE dealloc_c2( array, name, routine )
+END
+SUBROUTINE dealloc_c3( array, name, routine )
+END
+SUBROUTINE dealloc_c4( array, name, routine )
+END
+SUBROUTINE dealloc_c5( array, name, routine )
+ END
+SUBROUTINE dealloc_z1( array, name, routine )
+END
+SUBROUTINE dealloc_z2( array, name, routine )
+END
+SUBROUTINE dealloc_z3( array, name, routine )
+END
+SUBROUTINE dealloc_z4( array, name, routine )
+END
+SUBROUTINE dealloc_z5( array, name, routine )
+ END
+SUBROUTINE dealloc_l1( array, name, routine )
+END
+SUBROUTINE dealloc_l2( array, name, routine )
+END
+SUBROUTINE dealloc_l3( array, name, routine )
+END
+SUBROUTINE dealloc_l4( array, name, routine )
+ END
+SUBROUTINE dealloc_l5( array, name, routine )
+ END
+SUBROUTINE dealloc_s1( array, name, routine )
+END
+SUBROUTINE options( final_bounds, common_bounds, old_bounds, new_bounds, copy, shrink )
+END
+SUBROUTINE alloc_err( ierr, name, routine, bounds )
+END
+SUBROUTINE alloc_count( delta_size, type, name, routine )
+END
+END
diff --git a/flang/test/Semantics/Inputs/modfile73-b.f90 b/flang/test/Semantics/Inputs/modfile73-b.f90
new file mode 100644
index 0000000000000..3b9c72ab507b9
--- /dev/null
+++ b/flang/test/Semantics/Inputs/modfile73-b.f90
@@ -0,0 +1,89 @@
+module modfile73ba
+ use modfile73a, only: re_alloc, de_alloc
+ charactermod_name
+ type lData1D
+ integer refCount
+ character id
+ character name
+ end type
+ type TYPE_NAME
+ type(lData1D), pointer :: data => null()
+ end type
+ interface refcount
+ end interface
+ interface initialized
+ end interface
+ interface same
+ end interface
+CONTAINS
+ subroutine init_(this)
+ end
+ subroutine delete_(this)
+ end
+ subroutine assign_(this, other)
+ end
+ function initialized_(thisinit)
+ end
+ function same_(this1,this2same)
+ end
+ function refcount_(thiscount)
+ end
+ function id_(thisstr)
+ end
+ function name_(this) result(str)
+ type(TYPE_NAME) this
+ character(len_trim(this%data%name)) str
+ end
+ subroutine tag_new_object(this)
+ end
+ subroutine delete_Data(a1d_data)
+ end
+end
+
+module modfile73bb
+ use modfile73a, only: re_alloc, de_alloc
+ charactermod_name
+ type lData1D
+ integer refCount
+ character id
+ character name
+logical, pointer :: val => null()
+ end type
+ TYPE_NAME
+ type(lData1D), pointer :: data => null()
+ end type
+ PRIVATE
+ public TYPE_NAME
+ public initdelete, assignment, refcount, id
+ public name
+ public allocated
+ interface init
+ end interface
+ interface delete
+ end interface
+ interface initialized
+ subroutine die(str)
+ end
+ end interface
+CONTAINS
+ subroutine init_(this)
+ end
+ subroutine delete_(this)
+ end
+ subroutine assign_(this, other)
+ end
+ function initialized_(thisinit)
+ end
+ function same_(this1,this2same)
+ end
+ function refcount_(thiscount)
+ end
+ function id_(thisstr)
+ end
+ function name_(thisstr)
+ end
+ subroutine tag_new_object(this)
+ end
+ subroutine delete_Data(a1d_data)
+ end
+end
diff --git a/flang/test/Semantics/Inputs/modfile73-c.f90 b/flang/test/Semantics/Inputs/modfile73-c.f90
new file mode 100644
index 0000000000000..abf76445d4619
--- /dev/null
+++ b/flang/test/Semantics/Inputs/modfile73-c.f90
@@ -0,0 +1,4 @@
+module modfile73c
+ type OrbitalDistribution_
+ end type
+ end
diff --git a/flang/test/Semantics/modfile73.f90 b/flang/test/Semantics/modfile73.f90
new file mode 100644
index 0000000000000..f27b293d79d99
--- /dev/null
+++ b/flang/test/Semantics/modfile73.f90
@@ -0,0 +1,53 @@
+! This test verifies that both invocations produce a consistent order in the
+! generated `.mod` file. Previous versions of Flang exhibited non-deterministic
+! behavior due to iterating over a set ordered by heap pointers. This issue was
+! particularly noticeable when using Flang as a library.
+
+! RUN: rm -rf %t && mkdir -p %t
+! RUN: %flang_fc1 \
+! RUN: -fsyntax-only \
+! RUN: -J%t \
+! RUN: %S/Inputs/modfile73-a.f90 \
+! RUN: %S/Inputs/modfile73-b.f90 \
+! RUN: %S/Inputs/modfile73-c.f90
+! RUN: %flang_fc1 -fsyntax-only -J%t %s
+! RUN: cat %t/modfile73.mod | FileCheck %s
+
+! RUN: rm -rf %t && mkdir -p %t
+! RUN: %flang_fc1 \
+! RUN: -fsyntax-only \
+! RUN: -J%t \
+! RUN: %S/Inputs/modfile73-a.f90 \
+! RUN: %S/Inputs/modfile73-b.f90 \
+! RUN: %S/Inputs/modfile73-c.f90 \
+! RUN: %s
+! RUN: cat %t/modfile73.mod | FileCheck %s
+
+ use modfile73ba
+end
+module modfile73
+ use modfile73bb
+ use modfile73c
+ CONTAINS
+ subroutine init_
+ end
+ subroutine delete_
+ end
+ subroutine assign_
+ end
+ function initialized_
+ end
+ function same_
+ end
+ function refcount_
+ end
+ function id_
+ end
+ function name_
+ end
+ subroutine tag_new_object
+ end
+end
+
+! CHECK: !need$ {{.*}} n modfile73bb
+! CHECK-NEXT: !need$ {{.*}} n modfile73c
More information about the flang-commits
mailing list