Skip to content

[flang] Add general symbol dependence collection utility #146968

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions flang/include/flang/Semantics/symbol-dependence.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//===-- include/flang/Semantics/symbol-dependence.h -------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef FORTRAN_SEMANTICS_SYMBOL_DEPENDENCE_H_
#define FORTRAN_SEMANTICS_SYMBOL_DEPENDENCE_H_

#include "flang/Semantics/symbol.h"

namespace Fortran::semantics {

// For a set or scope of symbols, computes the transitive closure of their
// dependences due to their types, bounds, specific procedures, interfaces,
// initialization, storage association, &c. Includes the original symbol
// or members of the original set. Does not include dependences from
// subprogram definitions, only their interfaces.
enum DependenceCollectionFlags {
NoDependenceCollectionFlags = 0,
IncludeOriginalSymbols = 1 << 0,
FollowUseAssociations = 1 << 1,
IncludeSpecificsOfGenerics = 1 << 2,
IncludeUsesOfGenerics = 1 << 3,
NotJustForOneModule = 1 << 4,
};

SymbolVector CollectAllDependences(const SymbolVector &,
int = NoDependenceCollectionFlags, const Scope * = nullptr);
SymbolVector CollectAllDependences(
const Scope &, int = NoDependenceCollectionFlags);

} // namespace Fortran::semantics
#endif // FORTRAN_SEMANTICS_SYMBOL_DEPENDENCE_H_
1 change: 1 addition & 0 deletions flang/lib/Semantics/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ add_flang_library(FortranSemantics
runtime-type-info.cpp
scope.cpp
semantics.cpp
symbol-dependence.cpp
symbol.cpp
tools.cpp
type.cpp
Expand Down
76 changes: 9 additions & 67 deletions flang/lib/Semantics/mod-file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "flang/Parser/unparse.h"
#include "flang/Semantics/scope.h"
#include "flang/Semantics/semantics.h"
#include "flang/Semantics/symbol-dependence.h"
#include "flang/Semantics/symbol.h"
#include "flang/Semantics/tools.h"
#include "llvm/Support/FileSystem.h"
Expand Down Expand Up @@ -223,72 +224,13 @@ std::string ModFileWriter::GetAsString(const Symbol &symbol) {
// Collect symbols from constant and specification expressions that are being
// referenced directly from other modules; they may require new USE
// associations.
static void HarvestSymbolsNeededFromOtherModules(
SourceOrderedSymbolSet &, const Scope &);
static void HarvestSymbolsNeededFromOtherModules(
SourceOrderedSymbolSet &set, const Symbol &symbol, const Scope &scope) {
auto HarvestBound{[&](const Bound &bound) {
if (const auto &expr{bound.GetExplicit()}) {
for (SymbolRef ref : evaluate::CollectSymbols(*expr)) {
set.emplace(*ref);
}
}
}};
auto HarvestShapeSpec{[&](const ShapeSpec &shapeSpec) {
HarvestBound(shapeSpec.lbound());
HarvestBound(shapeSpec.ubound());
}};
auto HarvestArraySpec{[&](const ArraySpec &arraySpec) {
for (const auto &shapeSpec : arraySpec) {
HarvestShapeSpec(shapeSpec);
}
}};

if (symbol.has<DerivedTypeDetails>()) {
if (symbol.scope()) {
HarvestSymbolsNeededFromOtherModules(set, *symbol.scope());
}
} else if (const auto &generic{symbol.detailsIf<GenericDetails>()};
generic && generic->derivedType()) {
const Symbol &dtSym{*generic->derivedType()};
if (dtSym.has<DerivedTypeDetails>()) {
if (dtSym.scope()) {
HarvestSymbolsNeededFromOtherModules(set, *dtSym.scope());
}
} else {
CHECK(dtSym.has<UseDetails>() || dtSym.has<UseErrorDetails>());
}
} else if (const auto *object{symbol.detailsIf<ObjectEntityDetails>()}) {
HarvestArraySpec(object->shape());
HarvestArraySpec(object->coshape());
if (IsNamedConstant(symbol) || scope.IsDerivedType()) {
if (object->init()) {
for (SymbolRef ref : evaluate::CollectSymbols(*object->init())) {
set.emplace(*ref);
}
}
}
} else if (const auto *proc{symbol.detailsIf<ProcEntityDetails>()}) {
if (proc->init() && *proc->init() && scope.IsDerivedType()) {
set.emplace(**proc->init());
}
} else if (const auto *subp{symbol.detailsIf<SubprogramDetails>()}) {
for (const Symbol *dummy : subp->dummyArgs()) {
if (dummy) {
HarvestSymbolsNeededFromOtherModules(set, *dummy, scope);
}
}
if (subp->isFunction()) {
HarvestSymbolsNeededFromOtherModules(set, subp->result(), scope);
}
}
}

static void HarvestSymbolsNeededFromOtherModules(
SourceOrderedSymbolSet &set, const Scope &scope) {
for (const auto &[_, symbol] : scope) {
HarvestSymbolsNeededFromOtherModules(set, *symbol, scope);
static SourceOrderedSymbolSet HarvestSymbolsNeededFromOtherModules(
const Scope &scope) {
SourceOrderedSymbolSet set;
for (const Symbol &symbol : CollectAllDependences(scope)) {
set.insert(symbol);
}
return set;
}

void ModFileWriter::PrepareRenamings(const Scope &scope) {
Expand All @@ -304,8 +246,8 @@ void ModFileWriter::PrepareRenamings(const Scope &scope) {
}
}
// Collect symbols needed from other modules
SourceOrderedSymbolSet symbolsNeeded;
HarvestSymbolsNeededFromOtherModules(symbolsNeeded, scope);
SourceOrderedSymbolSet symbolsNeeded{
HarvestSymbolsNeededFromOtherModules(scope)};
// Establish any necessary renamings of symbols in other modules
// to their names in this scope, creating those new names when needed.
auto &renamings{context_.moduleFileOutputRenamings()};
Expand Down
Loading
Loading