Skip to content

Commit d26c78b

Browse files
authored
[flang] handle indirect module variable use in internal procedure (#65324)
When a module variable is referenced inside an internal procedure, but the use statement for the module is inside the host, semantics may not create any symbols with HostAssocDetails directly under the internal procedure scope. So pft::getScopeVariableList, that is called in the bridge when lowering the internal procedure scope, failed to instantiate the module variables. This lead to "symbol is not mapped to any IR value" compile time errors. This patch fixes the issue by adding the variables to the list of "captured" global variables from the host program, so that they are instantiated as part of the `internalProcedureBindings` in the bridge. The rational of doing it that way instead of changing `getScopeVariableList` is that `getScopeVariableList` would have to import all the module variables used inside the host since it cannot know which ones are referenced inside the internal procedure from the semantics::Scope information. The fix in this patch only instantiates the module variables from the host that are actually referenced inside the internal procedure.
1 parent 0c81e6d commit d26c78b

File tree

3 files changed

+48
-6
lines changed

3 files changed

+48
-6
lines changed

flang/lib/Lower/Bridge.cpp

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,19 @@ class FirConverter : public Fortran::lower::AbstractConverter {
383383
declareFunction(f);
384384
}
385385

386+
/// Get the scope that is defining or using \p sym. The returned scope is not
387+
/// the ultimate scope, since this helper does not traverse use association.
388+
/// This allows capturing module variables that are referenced in an internal
389+
/// procedure but whose use statement is inside the host program.
390+
const Fortran::semantics::Scope &
391+
getSymbolHostScope(const Fortran::semantics::Symbol &sym) {
392+
const Fortran::semantics::Symbol *hostSymbol = &sym;
393+
while (const auto *details =
394+
hostSymbol->detailsIf<Fortran::semantics::HostAssocDetails>())
395+
hostSymbol = &details->symbol();
396+
return hostSymbol->owner();
397+
}
398+
386399
/// Collects the canonical list of all host associated symbols. These bindings
387400
/// must be aggregated into a tuple which can then be added to each of the
388401
/// internal procedure declarations and passed at each call site.
@@ -399,12 +412,12 @@ class FirConverter : public Fortran::lower::AbstractConverter {
399412
if (ultimate.has<Fortran::semantics::ObjectEntityDetails>() ||
400413
Fortran::semantics::IsProcedurePointer(ultimate) ||
401414
Fortran::semantics::IsDummy(sym) || namelistDetails) {
402-
const Fortran::semantics::Scope &ultimateScope = ultimate.owner();
403-
if (ultimateScope.kind() ==
415+
const Fortran::semantics::Scope &symbolScope = getSymbolHostScope(sym);
416+
if (symbolScope.kind() ==
404417
Fortran::semantics::Scope::Kind::MainProgram ||
405-
ultimateScope.kind() == Fortran::semantics::Scope::Kind::Subprogram)
406-
if (ultimateScope != *internalScope &&
407-
ultimateScope.Contains(*internalScope)) {
418+
symbolScope.kind() == Fortran::semantics::Scope::Kind::Subprogram)
419+
if (symbolScope != *internalScope &&
420+
symbolScope.Contains(*internalScope)) {
408421
if (namelistDetails) {
409422
// So far, namelist symbols are processed on the fly in IO and
410423
// the related namelist data structure is not added to the symbol
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
! Test instantiation of module variables inside an internal subprogram
2+
! where the use statement is inside the host program.
3+
! RUN: bbc -emit-hlfir -o - %s | FileCheck %s
4+
5+
module module_used_by_host
6+
implicit none
7+
integer :: indexed_by_var(2)
8+
integer :: ref_in_implied_do
9+
integer :: ref_in_forall(2)
10+
end module
11+
12+
subroutine host_procedure
13+
use module_used_by_host
14+
implicit none
15+
contains
16+
subroutine internal_procedure(i, mask)
17+
integer :: i
18+
logical :: mask(2)
19+
indexed_by_var(i) = 0
20+
print *, (/(ref_in_implied_do, integer::j=1,10)/)
21+
forall (integer::k = 1:2)
22+
ref_in_forall(k) = 0
23+
end forall
24+
end subroutine
25+
end subroutine
26+
! CHECK-LABEL: func.func @_QFhost_procedurePinternal_procedure(
27+
! CHECK: fir.address_of(@_QMmodule_used_by_hostEindexed_by_var) : !fir.ref<!fir.array<2xi32>>
28+
! CHECK: fir.address_of(@_QMmodule_used_by_hostEref_in_forall) : !fir.ref<!fir.array<2xi32>>
29+
! CHECK: fir.address_of(@_QMmodule_used_by_hostEref_in_implied_do) : !fir.ref<i32>

flang/test/Lower/explicit-interface-results-2.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ subroutine host5()
9494
implicit none
9595
call internal_proc_a()
9696
contains
97-
! CHECK-LABEL: func @_QFhost5Pinternal_proc_a() {
97+
! CHECK-LABEL: func @_QFhost5Pinternal_proc_a() attributes {fir.internal_proc} {
9898
subroutine internal_proc_a()
9999
call takes_array(return_array())
100100
! CHECK: %[[VAL_0:.*]] = fir.address_of(@_QMsome_moduleEn_module) : !fir.ref<i32>

0 commit comments

Comments
 (0)