Skip to content

Commit 21463a6

Browse files
committed
[flang] Don't emit needless symbols to hermetic module files
When emitting the dependent modules for a hermetic module file, omit symbols that are not necessary (directly or otherwise) for the declarations and definitions in the main module. (Includes #144618 as the first commit.)
1 parent 710d256 commit 21463a6

File tree

3 files changed

+57
-36
lines changed

3 files changed

+57
-36
lines changed

flang/lib/Semantics/mod-file.cpp

Lines changed: 54 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ struct ModHeader {
4848
};
4949

5050
static std::optional<SourceName> GetSubmoduleParent(const parser::Program &);
51-
static void CollectSymbols(
52-
const Scope &, SymbolVector &, SymbolVector &, SourceOrderedSymbolSet &);
51+
static void CollectSymbols(const Scope &, SymbolVector &, SymbolVector &,
52+
SourceOrderedSymbolSet &, UnorderedSymbolSet *);
5353
static void PutPassName(llvm::raw_ostream &, const std::optional<SourceName> &);
5454
static void PutInit(llvm::raw_ostream &, const Symbol &, const MaybeExpr &,
5555
const parser::Expr *, SemanticsContext &);
@@ -131,7 +131,7 @@ static std::string ModFileName(const SourceName &name,
131131
return ancestorName.empty() ? result : ancestorName + '-' + result;
132132
}
133133

134-
// Write the module file for symbol, which must be a module or submodule.
134+
// Writes the module file for symbol, which must be a module or submodule.
135135
void ModFileWriter::Write(const Symbol &symbol) {
136136
const auto &module{symbol.get<ModuleDetails>()};
137137
if (symbol.test(Symbol::Flag::ModFile) || module.moduleFileHash()) {
@@ -143,21 +143,30 @@ void ModFileWriter::Write(const Symbol &symbol) {
143143
std::string path{context_.moduleDirectory() + '/' +
144144
ModFileName(symbol.name(), ancestorName, context_.moduleFileSuffix())};
145145

146-
std::set<std::string> hermeticModuleNames;
147-
hermeticModuleNames.insert(symbol.name().ToString());
148146
UnorderedSymbolSet additionalModules;
147+
UnorderedSymbolSet dependenceClosure;
148+
if (hermeticModuleFileOutput_) {
149+
dependenceClosure = CollectAllDependences(
150+
DEREF(symbol.scope()), IncludeOriginalSymbols | FollowUseAssociations);
151+
}
149152
PutSymbols(DEREF(symbol.scope()),
150-
hermeticModuleFileOutput_ ? &additionalModules : nullptr);
153+
hermeticModuleFileOutput_ ? &additionalModules : nullptr,
154+
hermeticModuleFileOutput_ ? &dependenceClosure : nullptr);
155+
std::set<std::string> emittedModuleNames;
156+
emittedModuleNames.insert(symbol.name().ToString());
151157
auto asStr{GetAsString(symbol)};
158+
159+
// Emit additional modules for a hermetic module file
152160
while (!additionalModules.empty()) {
153161
UnorderedSymbolSet nextPass{std::move(additionalModules)};
154162
additionalModules.clear();
155163
for (const Symbol &modSym : nextPass) {
156164
if (!modSym.owner().IsIntrinsicModules() &&
157-
hermeticModuleNames.find(modSym.name().ToString()) ==
158-
hermeticModuleNames.end()) {
159-
hermeticModuleNames.insert(modSym.name().ToString());
160-
PutSymbols(DEREF(modSym.scope()), &additionalModules);
165+
emittedModuleNames.find(modSym.name().ToString()) ==
166+
emittedModuleNames.end()) {
167+
emittedModuleNames.insert(modSym.name().ToString());
168+
PutSymbols(
169+
DEREF(modSym.scope()), &additionalModules, &dependenceClosure);
161170
asStr += GetAsString(modSym);
162171
}
163172
}
@@ -178,7 +187,8 @@ void ModFileWriter::WriteClosure(llvm::raw_ostream &out, const Symbol &symbol,
178187
!nonIntrinsicModulesWritten.insert(symbol).second) {
179188
return;
180189
}
181-
PutSymbols(DEREF(symbol.scope()), /*hermeticModules=*/nullptr);
190+
PutSymbols(DEREF(symbol.scope()), /*hermeticModules=*/nullptr,
191+
/*dependenceClosure=*/nullptr);
182192
needsBuf_.clear(); // omit module checksums
183193
auto str{GetAsString(symbol)};
184194
for (auto depRef : std::move(usedNonIntrinsicModules_)) {
@@ -231,10 +241,11 @@ static void HarvestSymbolsNeededFromOtherModules(
231241
}
232242
}
233243

234-
void ModFileWriter::PrepareRenamings(const Scope &scope) {
244+
void ModFileWriter::PrepareRenamings(
245+
const Scope &scope, const UnorderedSymbolSet *dependenceClosure) {
235246
// Identify use-associated symbols already in scope under some name
236247
std::map<const Symbol *, const Symbol *> useMap;
237-
for (const auto &[name, symbolRef] : scope) {
248+
for (const auto &[_, symbolRef] : scope) {
238249
const Symbol *symbol{&*symbolRef};
239250
while (const auto *hostAssoc{symbol->detailsIf<HostAssocDetails>()}) {
240251
symbol = &hostAssoc->symbol();
@@ -249,38 +260,42 @@ void ModFileWriter::PrepareRenamings(const Scope &scope) {
249260
// Establish any necessary renamings of symbols in other modules
250261
// to their names in this scope, creating those new names when needed.
251262
auto &renamings{context_.moduleFileOutputRenamings()};
252-
for (SymbolRef s : symbolsNeeded) {
253-
if (s->owner().kind() != Scope::Kind::Module) {
263+
for (const Symbol &sym : symbolsNeeded) {
264+
if (sym.owner().kind() != Scope::Kind::Module) {
254265
// Not a USE'able name from a module's top scope;
255266
// component, binding, dummy argument, &c.
256267
continue;
257268
}
258-
const Scope *sMod{FindModuleContaining(s->owner())};
269+
const Scope *sMod{FindModuleContaining(sym.owner())};
259270
if (!sMod || sMod == &scope) {
260271
continue;
261272
}
262-
if (auto iter{useMap.find(&*s)}; iter != useMap.end()) {
263-
renamings.emplace(&*s, iter->second->name());
273+
if (dependenceClosure &&
274+
dependenceClosure->find(sym) == dependenceClosure->end()) {
264275
continue;
265276
}
266-
SourceName rename{s->name()};
267-
if (const Symbol * found{scope.FindSymbol(s->name())}) {
268-
if (found == &*s) {
277+
if (auto iter{useMap.find(&sym)}; iter != useMap.end()) {
278+
renamings.emplace(&sym, iter->second->name());
279+
continue;
280+
}
281+
SourceName rename{sym.name()};
282+
if (const Symbol *found{scope.FindSymbol(sym.name())}) {
283+
if (found == &sym) {
269284
continue; // available in scope
270285
}
271286
if (const auto *generic{found->detailsIf<GenericDetails>()}) {
272-
if (generic->derivedType() == &*s || generic->specific() == &*s) {
287+
if (generic->derivedType() == &sym || generic->specific() == &sym) {
273288
continue;
274289
}
275290
} else if (found->has<UseDetails>()) {
276-
if (&found->GetUltimate() == &*s) {
291+
if (&found->GetUltimate() == &sym) {
277292
continue; // already use-associated with same name
278293
}
279294
}
280-
if (&s->owner() != &found->owner()) { // Symbol needs renaming
295+
if (&sym.owner() != &found->owner()) { // Symbol needs renaming
281296
rename = scope.context().SaveTempName(
282297
DEREF(sMod->symbol()).name().ToString() + "$" +
283-
s->name().ToString());
298+
sym.name().ToString());
284299
}
285300
}
286301
// Symbol is used in this scope but not visible under its name
@@ -290,25 +305,26 @@ void ModFileWriter::PrepareRenamings(const Scope &scope) {
290305
uses_ << "use ";
291306
}
292307
uses_ << DEREF(sMod->symbol()).name() << ",only:";
293-
if (rename != s->name()) {
308+
if (rename != sym.name()) {
294309
uses_ << rename << "=>";
295-
renamings.emplace(&s->GetUltimate(), rename);
310+
renamings.emplace(&sym.GetUltimate(), rename);
296311
}
297-
uses_ << s->name() << '\n';
312+
uses_ << sym.name() << '\n';
298313
useExtraAttrs_ << "private::" << rename << '\n';
299314
}
300315
}
301316

302317
// Put out the visible symbols from scope.
303-
void ModFileWriter::PutSymbols(
304-
const Scope &scope, UnorderedSymbolSet *hermeticModules) {
318+
void ModFileWriter::PutSymbols(const Scope &scope,
319+
UnorderedSymbolSet *hermeticModules,
320+
UnorderedSymbolSet *dependenceClosure) {
305321
SymbolVector sorted;
306322
SymbolVector uses;
307323
auto &renamings{context_.moduleFileOutputRenamings()};
308324
auto previousRenamings{std::move(renamings)};
309-
PrepareRenamings(scope);
325+
PrepareRenamings(scope, dependenceClosure);
310326
SourceOrderedSymbolSet modules;
311-
CollectSymbols(scope, sorted, uses, modules);
327+
CollectSymbols(scope, sorted, uses, modules, dependenceClosure);
312328
// Write module files for dependences first so that their
313329
// hashes are known.
314330
for (const Symbol &mod : modules) {
@@ -792,12 +808,17 @@ void ModFileWriter::PutUseExtraAttr(
792808
// Collect the symbols of this scope sorted by their original order, not name.
793809
// Generics and namelists are exceptions: they are sorted after other symbols.
794810
void CollectSymbols(const Scope &scope, SymbolVector &sorted,
795-
SymbolVector &uses, SourceOrderedSymbolSet &modules) {
811+
SymbolVector &uses, SourceOrderedSymbolSet &modules,
812+
UnorderedSymbolSet *dependenceClosure) {
796813
SymbolVector namelist, generics;
797814
auto symbols{scope.GetSymbols()};
798815
std::size_t commonSize{scope.commonBlocks().size()};
799816
sorted.reserve(symbols.size() + commonSize);
800817
for (const Symbol &symbol : symbols) {
818+
if (dependenceClosure &&
819+
dependenceClosure->find(symbol) == dependenceClosure->end()) {
820+
continue; // needless for the main module
821+
}
801822
const auto *generic{symbol.detailsIf<GenericDetails>()};
802823
if (generic) {
803824
uses.insert(uses.end(), generic->uses().begin(), generic->uses().end());

flang/lib/Semantics/mod-file.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,9 @@ class ModFileWriter {
6767
void WriteOne(const Scope &);
6868
void Write(const Symbol &);
6969
std::string GetAsString(const Symbol &);
70-
void PrepareRenamings(const Scope &);
71-
void PutSymbols(const Scope &, UnorderedSymbolSet *hermetic);
70+
void PrepareRenamings(const Scope &, const UnorderedSymbolSet *);
71+
void PutSymbols(const Scope &, UnorderedSymbolSet *hermetic,
72+
UnorderedSymbolSet *dependenceClosure);
7273
// Returns true if a derived type with bindings and "contains" was emitted
7374
bool PutComponents(const Symbol &);
7475
void PutSymbol(llvm::raw_ostream &, const Symbol &);

flang/test/Semantics/modfile78.F90

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ module modfile78c
2727
!CHECK: integer(4)::global_variable
2828
!CHECK: end
2929
!CHECK: module modfile78b
30-
!CHECK: use modfile78a,only:global_variable
3130
!CHECK: contains
3231
!CHECK: subroutine test()
3332
!CHECK: end

0 commit comments

Comments
 (0)