[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