@@ -62,6 +62,12 @@ struct WasmSignatureDenseMapInfo {
62
62
}
63
63
};
64
64
65
+ // A Wasm export to be written into the export section.
66
+ struct WasmExportEntry {
67
+ const Symbol *Symbol;
68
+ StringRef FieldName; // may not match the Symbol name
69
+ };
70
+
65
71
// The writer writes a SymbolTable result to a file.
66
72
class Writer {
67
73
public:
@@ -76,6 +82,7 @@ class Writer {
76
82
void calculateInitFunctions ();
77
83
void assignIndexes ();
78
84
void calculateImports ();
85
+ void calculateExports ();
79
86
void calculateTypes ();
80
87
void createOutputSegments ();
81
88
void layoutMemory ();
@@ -114,6 +121,7 @@ class Writer {
114
121
DenseMap<WasmSignature, int32_t , WasmSignatureDenseMapInfo> TypeIndices;
115
122
std::vector<const Symbol *> ImportedFunctions;
116
123
std::vector<const Symbol *> ImportedGlobals;
124
+ std::vector<WasmExportEntry> ExportedSymbols;
117
125
std::vector<const Symbol *> DefinedGlobals;
118
126
std::vector<InputFunction *> DefinedFunctions;
119
127
std::vector<const Symbol *> IndirectFunctions;
@@ -259,35 +267,8 @@ void Writer::createTableSection() {
259
267
260
268
void Writer::createExportSection () {
261
269
bool ExportMemory = !Config->Relocatable && !Config->ImportMemory ;
262
- Symbol *EntrySym = Symtab->find (Config->Entry );
263
- bool ExportEntry = !Config->Relocatable && EntrySym && EntrySym->isDefined ();
264
- bool ExportHidden = Config->EmitRelocs ;
265
-
266
- uint32_t NumExports = ExportMemory ? 1 : 0 ;
267
-
268
- std::vector<const Symbol *> SymbolExports;
269
- if (ExportEntry)
270
- SymbolExports.emplace_back (EntrySym);
271
-
272
- for (const Symbol *Sym : Symtab->getSymbols ()) {
273
- if (Sym->isUndefined () || Sym->isGlobal ())
274
- continue ;
275
- if (Sym->isHidden () && !ExportHidden)
276
- continue ;
277
- if (ExportEntry && Sym == EntrySym)
278
- continue ;
279
- SymbolExports.emplace_back (Sym);
280
- }
281
270
282
- for (const Symbol *Sym : DefinedGlobals) {
283
- // Can't export the SP right now because it mutable and mutable globals
284
- // connot be exported.
285
- if (Sym == Config->StackPointerSymbol )
286
- continue ;
287
- SymbolExports.emplace_back (Sym);
288
- }
289
-
290
- NumExports += SymbolExports.size ();
271
+ uint32_t NumExports = (ExportMemory ? 1 : 0 ) + ExportedSymbols.size ();
291
272
if (!NumExports)
292
273
return ;
293
274
@@ -304,12 +285,12 @@ void Writer::createExportSection() {
304
285
writeExport (OS, MemoryExport);
305
286
}
306
287
307
- for (const Symbol *Sym : SymbolExports ) {
308
- DEBUG (dbgs () << " Export: " << Sym ->getName () << " \n " );
288
+ for (const WasmExportEntry &E : ExportedSymbols ) {
289
+ DEBUG (dbgs () << " Export: " << E. Symbol ->getName () << " \n " );
309
290
WasmExport Export;
310
- Export.Name = Sym-> getName () ;
311
- Export.Index = Sym ->getOutputIndex ();
312
- if (Sym ->isFunction ())
291
+ Export.Name = E. FieldName ;
292
+ Export.Index = E. Symbol ->getOutputIndex ();
293
+ if (E. Symbol ->isFunction ())
313
294
Export.Kind = WASM_EXTERNAL_FUNCTION;
314
295
else
315
296
Export.Kind = WASM_EXTERNAL_GLOBAL;
@@ -404,6 +385,26 @@ void Writer::createLinkingSection() {
404
385
if (!Config->Relocatable )
405
386
return ;
406
387
388
+ std::vector<std::pair<StringRef, uint32_t >> SymbolInfo;
389
+ for (const WasmExportEntry &E : ExportedSymbols) {
390
+ uint32_t Flags =
391
+ (E.Symbol ->isLocal () ? WASM_SYMBOL_BINDING_LOCAL :
392
+ E.Symbol ->isWeak () ? WASM_SYMBOL_BINDING_WEAK : 0 ) |
393
+ (E.Symbol ->isHidden () ? WASM_SYMBOL_VISIBILITY_HIDDEN : 0 );
394
+ if (Flags)
395
+ SymbolInfo.emplace_back (E.FieldName , Flags);
396
+ }
397
+ if (!SymbolInfo.empty ()) {
398
+ SubSection SubSection (WASM_SYMBOL_INFO);
399
+ writeUleb128 (SubSection.getStream (), SymbolInfo.size (), " num sym info" );
400
+ for (auto Pair: SymbolInfo) {
401
+ writeStr (SubSection.getStream (), Pair.first , " sym name" );
402
+ writeUleb128 (SubSection.getStream (), Pair.second , " sym flags" );
403
+ }
404
+ SubSection.finalizeContents ();
405
+ SubSection.writeToStream (OS);
406
+ }
407
+
407
408
if (Segments.size ()) {
408
409
SubSection SubSection (WASM_SEGMENT_INFO);
409
410
writeUleb128 (SubSection.getStream (), Segments.size (), " num data segments" );
@@ -608,6 +609,64 @@ void Writer::calculateImports() {
608
609
}
609
610
}
610
611
612
+ void Writer::calculateExports () {
613
+ Symbol *EntrySym = Symtab->find (Config->Entry );
614
+ bool ExportEntry = !Config->Relocatable && EntrySym && EntrySym->isDefined ();
615
+ bool ExportHidden = Config->EmitRelocs ;
616
+ StringSet<> UsedNames;
617
+ auto BudgeLocalName = [&](const Symbol *Sym) {
618
+ StringRef SymName = Sym->getName ();
619
+ // We can't budge non-local names.
620
+ if (!Sym->isLocal ())
621
+ return SymName;
622
+ // We must budge local names that have a collision with a symbol that we
623
+ // haven't yet processed.
624
+ if (!Symtab->find (SymName) && UsedNames.insert (SymName).second )
625
+ return SymName;
626
+ for (unsigned I = 1 ; ; ++I) {
627
+ std::string NameBuf = (SymName + " ." + Twine (I)).str ();
628
+ if (!UsedNames.count (NameBuf)) {
629
+ StringRef Name = Saver.save (NameBuf);
630
+ UsedNames.insert (Name); // Insert must use safe StringRef from save()
631
+ return Name;
632
+ }
633
+ }
634
+ };
635
+
636
+ if (ExportEntry)
637
+ ExportedSymbols.emplace_back (WasmExportEntry{EntrySym, EntrySym->getName ()});
638
+
639
+ if (Config->CtorSymbol && ExportHidden &&
640
+ !(ExportEntry && Config->CtorSymbol == EntrySym))
641
+ ExportedSymbols.emplace_back (
642
+ WasmExportEntry{Config->CtorSymbol , Config->CtorSymbol ->getName ()});
643
+
644
+ for (ObjFile *File : Symtab->ObjectFiles ) {
645
+ for (Symbol *Sym : File->getSymbols ()) {
646
+ if (!Sym->isDefined () || File != Sym->getFile ())
647
+ continue ;
648
+ if (Sym->isGlobal ())
649
+ continue ;
650
+ if (Sym->getFunction ()->Discarded )
651
+ continue ;
652
+
653
+ if ((Sym->isHidden () || Sym->isLocal ()) && !ExportHidden)
654
+ continue ;
655
+ if (ExportEntry && Sym == EntrySym)
656
+ continue ;
657
+ ExportedSymbols.emplace_back (WasmExportEntry{Sym, BudgeLocalName (Sym)});
658
+ }
659
+ }
660
+
661
+ for (const Symbol *Sym : DefinedGlobals) {
662
+ // Can't export the SP right now because it's mutable and mutable globals
663
+ // cannot be exported.
664
+ if (Sym == Config->StackPointerSymbol )
665
+ continue ;
666
+ ExportedSymbols.emplace_back (WasmExportEntry{Sym, BudgeLocalName (Sym)});
667
+ }
668
+ }
669
+
611
670
uint32_t Writer::lookupType (const WasmSignature &Sig) {
612
671
auto It = TypeIndices.find (Sig);
613
672
if (It == TypeIndices.end ()) {
@@ -793,6 +852,8 @@ void Writer::run() {
793
852
calculateImports ();
794
853
log (" -- assignIndexes" );
795
854
assignIndexes ();
855
+ log (" -- calculateExports" );
856
+ calculateExports ();
796
857
log (" -- calculateInitFunctions" );
797
858
calculateInitFunctions ();
798
859
if (!Config->Relocatable )
0 commit comments