summaryrefslogtreecommitdiffstats
path: root/lld/wasm/Writer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/wasm/Writer.cpp')
-rw-r--r--lld/wasm/Writer.cpp127
1 files changed, 94 insertions, 33 deletions
diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp
index 14fc90e9751..4cefe3a473e 100644
--- a/lld/wasm/Writer.cpp
+++ b/lld/wasm/Writer.cpp
@@ -62,6 +62,12 @@ struct WasmSignatureDenseMapInfo {
}
};
+// A Wasm export to be written into the export section.
+struct WasmExportEntry {
+ const Symbol *Symbol;
+ StringRef FieldName; // may not match the Symbol name
+};
+
// The writer writes a SymbolTable result to a file.
class Writer {
public:
@@ -76,6 +82,7 @@ private:
void calculateInitFunctions();
void assignIndexes();
void calculateImports();
+ void calculateExports();
void calculateTypes();
void createOutputSegments();
void layoutMemory();
@@ -114,6 +121,7 @@ private:
DenseMap<WasmSignature, int32_t, WasmSignatureDenseMapInfo> TypeIndices;
std::vector<const Symbol *> ImportedFunctions;
std::vector<const Symbol *> ImportedGlobals;
+ std::vector<WasmExportEntry> ExportedSymbols;
std::vector<const Symbol *> DefinedGlobals;
std::vector<InputFunction *> DefinedFunctions;
std::vector<const Symbol *> IndirectFunctions;
@@ -259,35 +267,8 @@ void Writer::createTableSection() {
void Writer::createExportSection() {
bool ExportMemory = !Config->Relocatable && !Config->ImportMemory;
- Symbol *EntrySym = Symtab->find(Config->Entry);
- bool ExportEntry = !Config->Relocatable && EntrySym && EntrySym->isDefined();
- bool ExportHidden = Config->EmitRelocs;
-
- uint32_t NumExports = ExportMemory ? 1 : 0;
-
- std::vector<const Symbol *> SymbolExports;
- if (ExportEntry)
- SymbolExports.emplace_back(EntrySym);
-
- for (const Symbol *Sym : Symtab->getSymbols()) {
- if (Sym->isUndefined() || Sym->isGlobal())
- continue;
- if (Sym->isHidden() && !ExportHidden)
- continue;
- if (ExportEntry && Sym == EntrySym)
- continue;
- SymbolExports.emplace_back(Sym);
- }
- for (const Symbol *Sym : DefinedGlobals) {
- // Can't export the SP right now because it mutable and mutable globals
- // connot be exported.
- if (Sym == Config->StackPointerSymbol)
- continue;
- SymbolExports.emplace_back(Sym);
- }
-
- NumExports += SymbolExports.size();
+ uint32_t NumExports = (ExportMemory ? 1 : 0) + ExportedSymbols.size();
if (!NumExports)
return;
@@ -304,12 +285,12 @@ void Writer::createExportSection() {
writeExport(OS, MemoryExport);
}
- for (const Symbol *Sym : SymbolExports) {
- DEBUG(dbgs() << "Export: " << Sym->getName() << "\n");
+ for (const WasmExportEntry &E : ExportedSymbols) {
+ DEBUG(dbgs() << "Export: " << E.Symbol->getName() << "\n");
WasmExport Export;
- Export.Name = Sym->getName();
- Export.Index = Sym->getOutputIndex();
- if (Sym->isFunction())
+ Export.Name = E.FieldName;
+ Export.Index = E.Symbol->getOutputIndex();
+ if (E.Symbol->isFunction())
Export.Kind = WASM_EXTERNAL_FUNCTION;
else
Export.Kind = WASM_EXTERNAL_GLOBAL;
@@ -404,6 +385,26 @@ void Writer::createLinkingSection() {
if (!Config->Relocatable)
return;
+ std::vector<std::pair<StringRef, uint32_t>> SymbolInfo;
+ for (const WasmExportEntry &E : ExportedSymbols) {
+ uint32_t Flags =
+ (E.Symbol->isLocal() ? WASM_SYMBOL_BINDING_LOCAL :
+ E.Symbol->isWeak() ? WASM_SYMBOL_BINDING_WEAK : 0) |
+ (E.Symbol->isHidden() ? WASM_SYMBOL_VISIBILITY_HIDDEN : 0);
+ if (Flags)
+ SymbolInfo.emplace_back(E.FieldName, Flags);
+ }
+ if (!SymbolInfo.empty()) {
+ SubSection SubSection(WASM_SYMBOL_INFO);
+ writeUleb128(SubSection.getStream(), SymbolInfo.size(), "num sym info");
+ for (auto Pair: SymbolInfo) {
+ writeStr(SubSection.getStream(), Pair.first, "sym name");
+ writeUleb128(SubSection.getStream(), Pair.second, "sym flags");
+ }
+ SubSection.finalizeContents();
+ SubSection.writeToStream(OS);
+ }
+
if (Segments.size()) {
SubSection SubSection(WASM_SEGMENT_INFO);
writeUleb128(SubSection.getStream(), Segments.size(), "num data segments");
@@ -608,6 +609,64 @@ void Writer::calculateImports() {
}
}
+void Writer::calculateExports() {
+ Symbol *EntrySym = Symtab->find(Config->Entry);
+ bool ExportEntry = !Config->Relocatable && EntrySym && EntrySym->isDefined();
+ bool ExportHidden = Config->EmitRelocs;
+ StringSet<> UsedNames;
+ auto BudgeLocalName = [&](const Symbol *Sym) {
+ StringRef SymName = Sym->getName();
+ // We can't budge non-local names.
+ if (!Sym->isLocal())
+ return SymName;
+ // We must budge local names that have a collision with a symbol that we
+ // haven't yet processed.
+ if (!Symtab->find(SymName) && UsedNames.insert(SymName).second)
+ return SymName;
+ for (unsigned I = 1; ; ++I) {
+ std::string NameBuf = (SymName + "." + Twine(I)).str();
+ if (!UsedNames.count(NameBuf)) {
+ StringRef Name = Saver.save(NameBuf);
+ UsedNames.insert(Name); // Insert must use safe StringRef from save()
+ return Name;
+ }
+ }
+ };
+
+ if (ExportEntry)
+ ExportedSymbols.emplace_back(WasmExportEntry{EntrySym, EntrySym->getName()});
+
+ if (Config->CtorSymbol && ExportHidden &&
+ !(ExportEntry && Config->CtorSymbol == EntrySym))
+ ExportedSymbols.emplace_back(
+ WasmExportEntry{Config->CtorSymbol, Config->CtorSymbol->getName()});
+
+ for (ObjFile *File : Symtab->ObjectFiles) {
+ for (Symbol *Sym : File->getSymbols()) {
+ if (!Sym->isDefined() || File != Sym->getFile())
+ continue;
+ if (Sym->isGlobal())
+ continue;
+ if (Sym->getFunction()->Discarded)
+ continue;
+
+ if ((Sym->isHidden() || Sym->isLocal()) && !ExportHidden)
+ continue;
+ if (ExportEntry && Sym == EntrySym)
+ continue;
+ ExportedSymbols.emplace_back(WasmExportEntry{Sym, BudgeLocalName(Sym)});
+ }
+ }
+
+ for (const Symbol *Sym : DefinedGlobals) {
+ // Can't export the SP right now because it's mutable and mutable globals
+ // cannot be exported.
+ if (Sym == Config->StackPointerSymbol)
+ continue;
+ ExportedSymbols.emplace_back(WasmExportEntry{Sym, BudgeLocalName(Sym)});
+ }
+}
+
uint32_t Writer::lookupType(const WasmSignature &Sig) {
auto It = TypeIndices.find(Sig);
if (It == TypeIndices.end()) {
@@ -793,6 +852,8 @@ void Writer::run() {
calculateImports();
log("-- assignIndexes");
assignIndexes();
+ log("-- calculateExports");
+ calculateExports();
log("-- calculateInitFunctions");
calculateInitFunctions();
if (!Config->Relocatable)
OpenPOWER on IntegriCloud