@@ -48,8 +48,8 @@ struct ModHeader {
48
48
};
49
49
50
50
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 * );
53
53
static void PutPassName (llvm::raw_ostream &, const std::optional<SourceName> &);
54
54
static void PutInit (llvm::raw_ostream &, const Symbol &, const MaybeExpr &,
55
55
const parser::Expr *, SemanticsContext &);
@@ -131,7 +131,7 @@ static std::string ModFileName(const SourceName &name,
131
131
return ancestorName.empty () ? result : ancestorName + ' -' + result;
132
132
}
133
133
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.
135
135
void ModFileWriter::Write (const Symbol &symbol) {
136
136
const auto &module {symbol.get <ModuleDetails>()};
137
137
if (symbol.test (Symbol::Flag::ModFile) || module .moduleFileHash ()) {
@@ -143,21 +143,30 @@ void ModFileWriter::Write(const Symbol &symbol) {
143
143
std::string path{context_.moduleDirectory () + ' /' +
144
144
ModFileName (symbol.name (), ancestorName, context_.moduleFileSuffix ())};
145
145
146
- std::set<std::string> hermeticModuleNames;
147
- hermeticModuleNames.insert (symbol.name ().ToString ());
148
146
UnorderedSymbolSet additionalModules;
147
+ UnorderedSymbolSet dependenceClosure;
148
+ if (hermeticModuleFileOutput_) {
149
+ dependenceClosure = CollectAllDependences (
150
+ DEREF (symbol.scope ()), IncludeOriginalSymbols | FollowUseAssociations);
151
+ }
149
152
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 ());
151
157
auto asStr{GetAsString (symbol)};
158
+
159
+ // Emit additional modules for a hermetic module file
152
160
while (!additionalModules.empty ()) {
153
161
UnorderedSymbolSet nextPass{std::move (additionalModules)};
154
162
additionalModules.clear ();
155
163
for (const Symbol &modSym : nextPass) {
156
164
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);
161
170
asStr += GetAsString (modSym);
162
171
}
163
172
}
@@ -178,7 +187,8 @@ void ModFileWriter::WriteClosure(llvm::raw_ostream &out, const Symbol &symbol,
178
187
!nonIntrinsicModulesWritten.insert (symbol).second ) {
179
188
return ;
180
189
}
181
- PutSymbols (DEREF (symbol.scope ()), /* hermeticModules=*/ nullptr );
190
+ PutSymbols (DEREF (symbol.scope ()), /* hermeticModules=*/ nullptr ,
191
+ /* dependenceClosure=*/ nullptr );
182
192
needsBuf_.clear (); // omit module checksums
183
193
auto str{GetAsString (symbol)};
184
194
for (auto depRef : std::move (usedNonIntrinsicModules_)) {
@@ -231,10 +241,11 @@ static void HarvestSymbolsNeededFromOtherModules(
231
241
}
232
242
}
233
243
234
- void ModFileWriter::PrepareRenamings (const Scope &scope) {
244
+ void ModFileWriter::PrepareRenamings (
245
+ const Scope &scope, const UnorderedSymbolSet *dependenceClosure) {
235
246
// Identify use-associated symbols already in scope under some name
236
247
std::map<const Symbol *, const Symbol *> useMap;
237
- for (const auto &[name , symbolRef] : scope) {
248
+ for (const auto &[_ , symbolRef] : scope) {
238
249
const Symbol *symbol{&*symbolRef};
239
250
while (const auto *hostAssoc{symbol->detailsIf <HostAssocDetails>()}) {
240
251
symbol = &hostAssoc->symbol ();
@@ -249,38 +260,42 @@ void ModFileWriter::PrepareRenamings(const Scope &scope) {
249
260
// Establish any necessary renamings of symbols in other modules
250
261
// to their names in this scope, creating those new names when needed.
251
262
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) {
254
265
// Not a USE'able name from a module's top scope;
255
266
// component, binding, dummy argument, &c.
256
267
continue ;
257
268
}
258
- const Scope *sMod {FindModuleContaining (s-> owner ())};
269
+ const Scope *sMod {FindModuleContaining (sym. owner ())};
259
270
if (!sMod || sMod == &scope) {
260
271
continue ;
261
272
}
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 ()) {
264
275
continue ;
265
276
}
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) {
269
284
continue ; // available in scope
270
285
}
271
286
if (const auto *generic{found->detailsIf <GenericDetails>()}) {
272
- if (generic->derivedType () == &*s || generic->specific () == &*s ) {
287
+ if (generic->derivedType () == &sym || generic->specific () == &sym ) {
273
288
continue ;
274
289
}
275
290
} else if (found->has <UseDetails>()) {
276
- if (&found->GetUltimate () == &*s ) {
291
+ if (&found->GetUltimate () == &sym ) {
277
292
continue ; // already use-associated with same name
278
293
}
279
294
}
280
- if (&s-> owner () != &found->owner ()) { // Symbol needs renaming
295
+ if (&sym. owner () != &found->owner ()) { // Symbol needs renaming
281
296
rename = scope.context ().SaveTempName (
282
297
DEREF (sMod ->symbol ()).name ().ToString () + " $" +
283
- s-> name ().ToString ());
298
+ sym. name ().ToString ());
284
299
}
285
300
}
286
301
// Symbol is used in this scope but not visible under its name
@@ -290,25 +305,26 @@ void ModFileWriter::PrepareRenamings(const Scope &scope) {
290
305
uses_ << " use " ;
291
306
}
292
307
uses_ << DEREF (sMod ->symbol ()).name () << " ,only:" ;
293
- if (rename != s-> name ()) {
308
+ if (rename != sym. name ()) {
294
309
uses_ << rename << " =>" ;
295
- renamings.emplace (&s-> GetUltimate (), rename);
310
+ renamings.emplace (&sym. GetUltimate (), rename);
296
311
}
297
- uses_ << s-> name () << ' \n ' ;
312
+ uses_ << sym. name () << ' \n ' ;
298
313
useExtraAttrs_ << " private::" << rename << ' \n ' ;
299
314
}
300
315
}
301
316
302
317
// 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) {
305
321
SymbolVector sorted;
306
322
SymbolVector uses;
307
323
auto &renamings{context_.moduleFileOutputRenamings ()};
308
324
auto previousRenamings{std::move (renamings)};
309
- PrepareRenamings (scope);
325
+ PrepareRenamings (scope, dependenceClosure );
310
326
SourceOrderedSymbolSet modules;
311
- CollectSymbols (scope, sorted, uses, modules);
327
+ CollectSymbols (scope, sorted, uses, modules, dependenceClosure );
312
328
// Write module files for dependences first so that their
313
329
// hashes are known.
314
330
for (const Symbol &mod : modules) {
@@ -792,12 +808,17 @@ void ModFileWriter::PutUseExtraAttr(
792
808
// Collect the symbols of this scope sorted by their original order, not name.
793
809
// Generics and namelists are exceptions: they are sorted after other symbols.
794
810
void CollectSymbols (const Scope &scope, SymbolVector &sorted,
795
- SymbolVector &uses, SourceOrderedSymbolSet &modules) {
811
+ SymbolVector &uses, SourceOrderedSymbolSet &modules,
812
+ UnorderedSymbolSet *dependenceClosure) {
796
813
SymbolVector namelist, generics;
797
814
auto symbols{scope.GetSymbols ()};
798
815
std::size_t commonSize{scope.commonBlocks ().size ()};
799
816
sorted.reserve (symbols.size () + commonSize);
800
817
for (const Symbol &symbol : symbols) {
818
+ if (dependenceClosure &&
819
+ dependenceClosure->find (symbol) == dependenceClosure->end ()) {
820
+ continue ; // needless for the main module
821
+ }
801
822
const auto *generic{symbol.detailsIf <GenericDetails>()};
802
823
if (generic) {
803
824
uses.insert (uses.end (), generic->uses ().begin (), generic->uses ().end ());
0 commit comments