@@ -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,26 +143,14 @@ 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
- UnorderedSymbolSet additionalModules;
149
- PutSymbols (DEREF (symbol.scope ()),
150
- hermeticModuleFileOutput_ ? &additionalModules : nullptr );
151
- auto asStr{GetAsString (symbol)};
152
- while (!additionalModules.empty ()) {
153
- UnorderedSymbolSet nextPass{std::move (additionalModules)};
154
- additionalModules.clear ();
155
- for (const Symbol &modSym : nextPass) {
156
- 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);
161
- asStr += GetAsString (modSym);
162
- }
163
- }
146
+ SymbolVector dependenceClosure;
147
+ if (hermeticModuleFileOutput_) {
148
+ dependenceClosure = CollectAllDependences (DEREF (symbol.scope ()),
149
+ FollowUseAssociations | IncludeSpecificsOfGenerics);
164
150
}
165
-
151
+ PutSymbols (DEREF (symbol.scope ()), hermeticModuleFileOutput_);
152
+ auto asStr{GetAsString (&symbol, symbol.name ().ToString ())};
153
+ asStr += PutDependencyModules (symbol.name ().ToString (), dependenceClosure);
166
154
ModuleCheckSumType checkSum;
167
155
if (std::error_code error{
168
156
WriteFile (path, asStr, checkSum, context_.debugModuleWriter ())}) {
@@ -178,9 +166,9 @@ void ModFileWriter::WriteClosure(llvm::raw_ostream &out, const Symbol &symbol,
178
166
!nonIntrinsicModulesWritten.insert (symbol).second ) {
179
167
return ;
180
168
}
181
- PutSymbols (DEREF (symbol.scope ()), /* hermeticModules =*/ nullptr );
169
+ PutSymbols (DEREF (symbol.scope ()), /* omitModules =*/ false );
182
170
needsBuf_.clear (); // omit module checksums
183
- auto str{GetAsString (symbol)};
171
+ auto str{GetAsString (& symbol, symbol. name (). ToString () )};
184
172
for (auto depRef : std::move (usedNonIntrinsicModules_)) {
185
173
WriteClosure (out, *depRef, nonIntrinsicModulesWritten);
186
174
}
@@ -189,22 +177,23 @@ void ModFileWriter::WriteClosure(llvm::raw_ostream &out, const Symbol &symbol,
189
177
190
178
// Return the entire body of the module file
191
179
// and clear saved uses, decls, and contains.
192
- std::string ModFileWriter::GetAsString (const Symbol & symbol) {
180
+ std::string ModFileWriter::GetAsString (const Symbol * symbol, std::string name ) {
193
181
std::string buf;
194
182
llvm::raw_string_ostream all{buf};
195
183
all << needs_.str ();
196
184
needs_.str ().clear ();
197
- auto &details{symbol.get <ModuleDetails>()};
198
- if (!details.isSubmodule ()) {
199
- all << " module " << symbol.name ();
185
+ const ModuleDetails *details{
186
+ symbol ? &symbol->get <ModuleDetails>() : nullptr };
187
+ if (!details || !details->isSubmodule ()) {
188
+ all << " module " << name;
200
189
} else {
201
- auto *parent{details. parent ()->symbol ()};
202
- auto *ancestor{details. ancestor ()->symbol ()};
190
+ auto *parent{details-> parent ()->symbol ()};
191
+ auto *ancestor{details-> ancestor ()->symbol ()};
203
192
all << " submodule(" << ancestor->name ();
204
193
if (parent != ancestor) {
205
194
all << ' :' << parent->name ();
206
195
}
207
- all << " ) " << symbol. name () ;
196
+ all << " ) " << name;
208
197
}
209
198
all << ' \n ' << uses_.str ();
210
199
uses_.str ().clear ();
@@ -234,7 +223,7 @@ static void HarvestSymbolsNeededFromOtherModules(
234
223
void ModFileWriter::PrepareRenamings (const Scope &scope) {
235
224
// Identify use-associated symbols already in scope under some name
236
225
std::map<const Symbol *, const Symbol *> useMap;
237
- for (const auto &[name , symbolRef] : scope) {
226
+ for (const auto &[_ , symbolRef] : scope) {
238
227
const Symbol *symbol{&*symbolRef};
239
228
while (const auto *hostAssoc{symbol->detailsIf <HostAssocDetails>()}) {
240
229
symbol = &hostAssoc->symbol ();
@@ -249,38 +238,38 @@ void ModFileWriter::PrepareRenamings(const Scope &scope) {
249
238
// Establish any necessary renamings of symbols in other modules
250
239
// to their names in this scope, creating those new names when needed.
251
240
auto &renamings{context_.moduleFileOutputRenamings ()};
252
- for (SymbolRef s : symbolsNeeded) {
253
- if (s-> owner ().kind () != Scope::Kind::Module) {
241
+ for (const Symbol &sym : symbolsNeeded) {
242
+ if (sym. owner ().kind () != Scope::Kind::Module) {
254
243
// Not a USE'able name from a module's top scope;
255
244
// component, binding, dummy argument, &c.
256
245
continue ;
257
246
}
258
- const Scope *sMod {FindModuleContaining (s-> owner ())};
247
+ const Scope *sMod {FindModuleContaining (sym. owner ())};
259
248
if (!sMod || sMod == &scope) {
260
249
continue ;
261
250
}
262
- if (auto iter{useMap.find (&*s )}; iter != useMap.end ()) {
263
- renamings.emplace (&*s , iter->second ->name ());
251
+ if (auto iter{useMap.find (&sym )}; iter != useMap.end ()) {
252
+ renamings.emplace (&sym , iter->second ->name ());
264
253
continue ;
265
254
}
266
- SourceName rename{s-> name ()};
267
- if (const Symbol * found{scope.FindSymbol (s-> name ())}) {
268
- if (found == &*s ) {
255
+ SourceName rename{sym. name ()};
256
+ if (const Symbol *found{scope.FindSymbol (sym. name ())}) {
257
+ if (found == &sym ) {
269
258
continue ; // available in scope
270
259
}
271
260
if (const auto *generic{found->detailsIf <GenericDetails>()}) {
272
- if (generic->derivedType () == &*s || generic->specific () == &*s ) {
261
+ if (generic->derivedType () == &sym || generic->specific () == &sym ) {
273
262
continue ;
274
263
}
275
264
} else if (found->has <UseDetails>()) {
276
- if (&found->GetUltimate () == &*s ) {
265
+ if (&found->GetUltimate () == &sym ) {
277
266
continue ; // already use-associated with same name
278
267
}
279
268
}
280
- if (&s-> owner () != &found->owner ()) { // Symbol needs renaming
269
+ if (&sym. owner () != &found->owner ()) { // Symbol needs renaming
281
270
rename = scope.context ().SaveTempName (
282
271
DEREF (sMod ->symbol ()).name ().ToString () + " $" +
283
- s-> name ().ToString ());
272
+ sym. name ().ToString ());
284
273
}
285
274
}
286
275
// Symbol is used in this scope but not visible under its name
@@ -290,31 +279,28 @@ void ModFileWriter::PrepareRenamings(const Scope &scope) {
290
279
uses_ << " use " ;
291
280
}
292
281
uses_ << DEREF (sMod ->symbol ()).name () << " ,only:" ;
293
- if (rename != s-> name ()) {
282
+ if (rename != sym. name ()) {
294
283
uses_ << rename << " =>" ;
295
- renamings.emplace (&s-> GetUltimate (), rename);
284
+ renamings.emplace (&sym. GetUltimate (), rename);
296
285
}
297
- uses_ << s-> name () << ' \n ' ;
286
+ uses_ << sym. name () << ' \n ' ;
298
287
useExtraAttrs_ << " private::" << rename << ' \n ' ;
299
288
}
300
289
}
301
290
302
291
// Put out the visible symbols from scope.
303
- void ModFileWriter::PutSymbols (
304
- const Scope &scope, UnorderedSymbolSet *hermeticModules) {
292
+ void ModFileWriter::PutSymbols (const Scope &scope, bool omitModules) {
305
293
SymbolVector sorted;
306
294
SymbolVector uses;
307
295
auto &renamings{context_.moduleFileOutputRenamings ()};
308
296
auto previousRenamings{std::move (renamings)};
309
297
PrepareRenamings (scope);
310
298
SourceOrderedSymbolSet modules;
311
299
CollectSymbols (scope, sorted, uses, modules);
312
- // Write module files for dependences first so that their
300
+ // Write module files for compiled dependency modules first so that their
313
301
// hashes are known.
314
- for (const Symbol &mod : modules) {
315
- if (hermeticModules) {
316
- hermeticModules->insert (mod);
317
- } else {
302
+ if (!omitModules) {
303
+ for (const Symbol &mod : modules) {
318
304
Write (mod);
319
305
// It's possible that the module's file already existed and
320
306
// without its own hash due to being embedded in a hermetic
@@ -352,6 +338,86 @@ void ModFileWriter::PutSymbols(
352
338
renamings = std::move (previousRenamings);
353
339
}
354
340
341
+ std::string ModFileWriter::PutDependencyModules (
342
+ std::string originalModuleName, const SymbolVector &revOrder) {
343
+ // Partition symbols by module name.
344
+ // Ignore symbols from intrinsic modules and the original module.
345
+ std::map<std::string, SymbolVector> perModuleName;
346
+ for (const Symbol &symbol : revOrder) {
347
+ if (const Scope *module {FindModuleContaining (symbol.owner ())}) {
348
+ if (!module ->parent ().IsIntrinsicModules ()) {
349
+ if (auto name{module ->GetName ()}) {
350
+ if (getenv (" PMK" ) && name->ToString () == originalModuleName)
351
+ llvm::errs () << " pmk: from original module: " << symbol << ' \n ' ;
352
+ perModuleName[name->ToString ()].emplace_back (symbol);
353
+ }
354
+ }
355
+ }
356
+ }
357
+ std::string result;
358
+ for (const auto &[moduleName, symbols] : perModuleName) {
359
+ if (moduleName != originalModuleName) {
360
+ result += PutDependencyModule (moduleName, symbols);
361
+ }
362
+ }
363
+ return result;
364
+ }
365
+
366
+ std::string ModFileWriter::PutDependencyModule (
367
+ const std::string &moduleName, const SymbolVector &symbols) {
368
+ SymbolVector order, namelists, generics;
369
+ std::set<std::string> names, commonNames, genericNames;
370
+ order.reserve (symbols.size ());
371
+ for (const Symbol &symbol : symbols) {
372
+ std::string symbolName{symbol.name ().ToString ()};
373
+ if (symbol.test (Symbol::Flag::ParentComp) ||
374
+ symbol.test (Symbol::Flag::CompilerCreated) ||
375
+ !symbol.owner ().IsModule ()) {
376
+ } else if (symbol.has <CommonBlockDetails>()) {
377
+ if (commonNames.find (symbolName) == commonNames.end ()) {
378
+ order.push_back (symbol);
379
+ commonNames.insert (symbolName);
380
+ }
381
+ } else if (const auto *generic{symbol.detailsIf <GenericDetails>()}) {
382
+ if (names.find (symbolName) == names.end ()) {
383
+ if (generic->specific () &&
384
+ &generic->specific ()->owner () == &symbol.owner ()) {
385
+ order.push_back (*generic->specific ());
386
+ names.insert (symbolName);
387
+ } else if (generic->derivedType () &&
388
+ &generic->derivedType ()->owner () == &symbol.owner ()) {
389
+ order.push_back (*generic->derivedType ());
390
+ names.insert (symbolName);
391
+ }
392
+ }
393
+ if (genericNames.find (symbolName) == genericNames.end ()) {
394
+ generics.push_back (symbol);
395
+ genericNames.insert (symbolName);
396
+ }
397
+ } else if (names.find (symbolName) != names.end ()) {
398
+ } else if (symbol.has <NamelistDetails>()) {
399
+ namelists.push_back (symbol);
400
+ names.insert (symbolName);
401
+ } else {
402
+ order.push_back (symbol);
403
+ names.insert (symbolName);
404
+ }
405
+ }
406
+ order.insert (order.end (), generics.begin (), generics.end ());
407
+ order.insert (order.end (), namelists.begin (), namelists.end ());
408
+ // Emit the symbols
409
+ std::string buf;
410
+ llvm::raw_string_ostream typeBindings{buf};
411
+ for (const Symbol &symbol : order) {
412
+ if (getenv (" PMK" ))
413
+ llvm::errs () << " pmk: putting " << symbol << ' \n ' ;
414
+ PutSymbol (typeBindings, symbol);
415
+ }
416
+ // pmk TODO: equivalence sets
417
+ CHECK (typeBindings.str ().empty ());
418
+ return GetAsString (nullptr , moduleName);
419
+ }
420
+
355
421
// Emit components in order
356
422
bool ModFileWriter::PutComponents (const Symbol &typeSymbol) {
357
423
const auto &scope{DEREF (typeSymbol.scope ())};
0 commit comments