[flang-commits] [flang] d26c78b - [flang] handle indirect module variable use in internal procedure (#65324)

via flang-commits flang-commits at lists.llvm.org
Wed Sep 6 00:07:49 PDT 2023


Author: jeanPerier
Date: 2023-09-06T09:07:45+02:00
New Revision: d26c78b2ad5ed0f3384d7a3ef4b4d894f2b1be3e

URL: https://github.com/llvm/llvm-project/commit/d26c78b2ad5ed0f3384d7a3ef4b4d894f2b1be3e
DIFF: https://github.com/llvm/llvm-project/commit/d26c78b2ad5ed0f3384d7a3ef4b4d894f2b1be3e.diff

LOG: [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.

Added: 
    flang/test/Lower/HLFIR/internal-procedures-2.f90

Modified: 
    flang/lib/Lower/Bridge.cpp
    flang/test/Lower/explicit-interface-results-2.f90

Removed: 
    


################################################################################
diff  --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index 5d5ac0f274773ed..d7dec54c76de5dc 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -383,6 +383,19 @@ class FirConverter : public Fortran::lower::AbstractConverter {
       declareFunction(f);
   }
 
+  /// Get the scope that is defining or using \p sym. The returned scope is not
+  /// the ultimate scope, since this helper does not traverse use association.
+  /// This allows capturing module variables that are referenced in an internal
+  /// procedure but whose use statement is inside the host program.
+  const Fortran::semantics::Scope &
+  getSymbolHostScope(const Fortran::semantics::Symbol &sym) {
+    const Fortran::semantics::Symbol *hostSymbol = &sym;
+    while (const auto *details =
+               hostSymbol->detailsIf<Fortran::semantics::HostAssocDetails>())
+      hostSymbol = &details->symbol();
+    return hostSymbol->owner();
+  }
+
   /// Collects the canonical list of all host associated symbols. These bindings
   /// must be aggregated into a tuple which can then be added to each of the
   /// internal procedure declarations and passed at each call site.
@@ -399,12 +412,12 @@ class FirConverter : public Fortran::lower::AbstractConverter {
       if (ultimate.has<Fortran::semantics::ObjectEntityDetails>() ||
           Fortran::semantics::IsProcedurePointer(ultimate) ||
           Fortran::semantics::IsDummy(sym) || namelistDetails) {
-        const Fortran::semantics::Scope &ultimateScope = ultimate.owner();
-        if (ultimateScope.kind() ==
+        const Fortran::semantics::Scope &symbolScope = getSymbolHostScope(sym);
+        if (symbolScope.kind() ==
                 Fortran::semantics::Scope::Kind::MainProgram ||
-            ultimateScope.kind() == Fortran::semantics::Scope::Kind::Subprogram)
-          if (ultimateScope != *internalScope &&
-              ultimateScope.Contains(*internalScope)) {
+            symbolScope.kind() == Fortran::semantics::Scope::Kind::Subprogram)
+          if (symbolScope != *internalScope &&
+              symbolScope.Contains(*internalScope)) {
             if (namelistDetails) {
               // So far, namelist symbols are processed on the fly in IO and
               // the related namelist data structure is not added to the symbol

diff  --git a/flang/test/Lower/HLFIR/internal-procedures-2.f90 b/flang/test/Lower/HLFIR/internal-procedures-2.f90
new file mode 100644
index 000000000000000..bb05545bef1aa27
--- /dev/null
+++ b/flang/test/Lower/HLFIR/internal-procedures-2.f90
@@ -0,0 +1,29 @@
+! Test instantiation of module variables inside an internal subprogram
+! where the use statement is inside the host program.
+! RUN: bbc -emit-hlfir -o - %s | FileCheck %s
+
+module module_used_by_host
+ implicit none
+ integer :: indexed_by_var(2)
+ integer :: ref_in_implied_do
+ integer :: ref_in_forall(2)
+end module
+
+subroutine host_procedure
+ use module_used_by_host
+ implicit none
+contains
+ subroutine internal_procedure(i, mask)
+  integer :: i
+  logical :: mask(2)
+  indexed_by_var(i) = 0
+  print *, (/(ref_in_implied_do, integer::j=1,10)/)
+  forall (integer::k = 1:2)
+    ref_in_forall(k) = 0
+  end forall
+ end subroutine
+end subroutine
+! CHECK-LABEL: func.func @_QFhost_procedurePinternal_procedure(
+! CHECK:    fir.address_of(@_QMmodule_used_by_hostEindexed_by_var) : !fir.ref<!fir.array<2xi32>>
+! CHECK:    fir.address_of(@_QMmodule_used_by_hostEref_in_forall) : !fir.ref<!fir.array<2xi32>>
+! CHECK:    fir.address_of(@_QMmodule_used_by_hostEref_in_implied_do) : !fir.ref<i32>

diff  --git a/flang/test/Lower/explicit-interface-results-2.f90 b/flang/test/Lower/explicit-interface-results-2.f90
index 06fa5e6ed480b0a..f77eb7157c237e7 100644
--- a/flang/test/Lower/explicit-interface-results-2.f90
+++ b/flang/test/Lower/explicit-interface-results-2.f90
@@ -94,7 +94,7 @@ subroutine host5()
   implicit none
   call internal_proc_a()
 contains
-! CHECK-LABEL: func @_QFhost5Pinternal_proc_a() {
+! CHECK-LABEL: func @_QFhost5Pinternal_proc_a() attributes {fir.internal_proc} {
   subroutine internal_proc_a()
     call takes_array(return_array())
 ! CHECK:  %[[VAL_0:.*]] = fir.address_of(@_QMsome_moduleEn_module) : !fir.ref<i32>


        


More information about the flang-commits mailing list