mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-18 19:16:43 +00:00
[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.
This commit is contained in:
parent
107fe0ec6c
commit
6eefadd8ef
@ -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()};
|
||||
|
197
flang/test/Semantics/Inputs/modfile73-a.f90
Normal file
197
flang/test/Semantics/Inputs/modfile73-a.f90
Normal file
@ -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
|
89
flang/test/Semantics/Inputs/modfile73-b.f90
Normal file
89
flang/test/Semantics/Inputs/modfile73-b.f90
Normal file
@ -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
|
4
flang/test/Semantics/Inputs/modfile73-c.f90
Normal file
4
flang/test/Semantics/Inputs/modfile73-c.f90
Normal file
@ -0,0 +1,4 @@
|
||||
module modfile73c
|
||||
type OrbitalDistribution_
|
||||
end type
|
||||
end
|
53
flang/test/Semantics/modfile73.f90
Normal file
53
flang/test/Semantics/modfile73.f90
Normal file
@ -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
|
Loading…
x
Reference in New Issue
Block a user