diff --git a/lld/include/lld/Common/LLVM.h b/lld/include/lld/Common/LLVM.h --- a/lld/include/lld/Common/LLVM.h +++ b/lld/include/lld/Common/LLVM.h @@ -49,6 +49,7 @@ struct WasmFunction; struct WasmGlobal; struct WasmGlobalType; +struct WasmInitExpr; struct WasmLimits; struct WasmRelocation; struct WasmSignature; @@ -91,6 +92,7 @@ using llvm::wasm::WasmFunction; using llvm::wasm::WasmGlobal; using llvm::wasm::WasmGlobalType; +using llvm::wasm::WasmInitExpr; using llvm::wasm::WasmLimits; using llvm::wasm::WasmRelocation; using llvm::wasm::WasmSignature; diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp --- a/lld/wasm/Driver.cpp +++ b/lld/wasm/Driver.cpp @@ -9,8 +9,7 @@ #include "lld/Common/Driver.h" #include "Config.h" #include "InputChunks.h" -#include "InputGlobal.h" -#include "InputTable.h" +#include "InputElement.h" #include "MarkLive.h" #include "SymbolTable.h" #include "Writer.h" diff --git a/lld/wasm/InputElement.h b/lld/wasm/InputElement.h new file mode 100644 --- /dev/null +++ b/lld/wasm/InputElement.h @@ -0,0 +1,101 @@ +//===- InputElement.h ----------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLD_WASM_INPUT_ELEMENT_H +#define LLD_WASM_INPUT_ELEMENT_H + +#include "Config.h" +#include "InputFiles.h" +#include "WriterUtils.h" +#include "lld/Common/LLVM.h" +#include "llvm/Object/Wasm.h" + +namespace lld { +namespace wasm { + +// Represents a single element (Global, Event, Table, etc) within an input +// file. +class InputElement { +protected: + InputElement(StringRef name, ObjFile *f) + : file(f), live(!config->gcSections), name(name) {} + +public: + StringRef getName() const { return name; } + uint32_t getAssignedIndex() const { return assignedIndex.getValue(); } + bool hasAssignedIndex() const { return assignedIndex.hasValue(); } + void assignIndex(uint32_t index) { + assert(!hasAssignedIndex()); + assignedIndex = index; + } + + ObjFile *file; + bool live = false; + +protected: + StringRef name; + llvm::Optional assignedIndex; +}; + +class InputGlobal : public InputElement { +public: + InputGlobal(const WasmGlobal &g, ObjFile *f) + : InputElement(g.SymbolName, f), type(g.Type), initExpr(g.InitExpr) {} + + const WasmGlobalType &getType() const { return type; } + const WasmInitExpr &getInitExpr() const { return initExpr; } + + void setPointerValue(uint64_t value) { + if (config->is64.getValueOr(false)) { + assert(initExpr.Opcode == llvm::wasm::WASM_OPCODE_I64_CONST); + initExpr.Value.Int64 = value; + } else { + assert(initExpr.Opcode == llvm::wasm::WASM_OPCODE_I32_CONST); + initExpr.Value.Int32 = value; + } + } + +private: + WasmGlobalType type; + WasmInitExpr initExpr; +}; + +class InputEvent : public InputElement { +public: + InputEvent(const WasmSignature &s, const WasmEvent &e, ObjFile *f) + : InputElement(e.SymbolName, f), signature(s), type(e.Type) {} + + const WasmEventType &getType() const { return type; } + + const WasmSignature &signature; + +private: + WasmEventType type; +}; + +class InputTable : public InputElement { +public: + InputTable(const WasmTable &t, ObjFile *f) + : InputElement(t.SymbolName, f), type(t.Type) {} + + const WasmTableType &getType() const { return type; } + void setLimits(const WasmLimits &limits) { type.Limits = limits; } + +private: + WasmTableType type; +}; + +} // namespace wasm + +inline std::string toString(const wasm::InputElement *d) { + return (toString(d->file) + ":(" + d->getName() + ")").str(); +} + +} // namespace lld + +#endif // LLD_WASM_INPUT_ELEMENT_H diff --git a/lld/wasm/InputEvent.h b/lld/wasm/InputEvent.h deleted file mode 100644 --- a/lld/wasm/InputEvent.h +++ /dev/null @@ -1,62 +0,0 @@ -//===- InputEvent.h ---------------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Wasm events are features that suspend the current execution and transfer the -// control flow to a corresponding handler. Currently the only supported event -// kind is exceptions. -// -//===----------------------------------------------------------------------===// - -#ifndef LLD_WASM_INPUT_EVENT_H -#define LLD_WASM_INPUT_EVENT_H - -#include "Config.h" -#include "InputFiles.h" -#include "WriterUtils.h" -#include "lld/Common/ErrorHandler.h" -#include "llvm/Object/Wasm.h" - -namespace lld { -namespace wasm { - -// Represents a single Wasm Event within an input file. These are combined to -// form the final EVENTS section. -class InputEvent { -public: - InputEvent(const WasmSignature &s, const WasmEvent &e, ObjFile *f) - : file(f), event(e), signature(s), live(!config->gcSections) {} - - StringRef getName() const { return event.SymbolName; } - const WasmEventType &getType() const { return event.Type; } - - uint32_t getEventIndex() const { return eventIndex.getValue(); } - bool hasEventIndex() const { return eventIndex.hasValue(); } - void setEventIndex(uint32_t index) { - assert(!hasEventIndex()); - eventIndex = index; - } - - ObjFile *file; - WasmEvent event; - const WasmSignature &signature; - - bool live = false; - -protected: - llvm::Optional eventIndex; -}; - -} // namespace wasm - -inline std::string toString(const wasm::InputEvent *e) { - return (toString(e->file) + ":(" + e->getName() + ")").str(); -} - -} // namespace lld - -#endif // LLD_WASM_INPUT_EVENT_H diff --git a/lld/wasm/InputFiles.cpp b/lld/wasm/InputFiles.cpp --- a/lld/wasm/InputFiles.cpp +++ b/lld/wasm/InputFiles.cpp @@ -9,9 +9,7 @@ #include "InputFiles.h" #include "Config.h" #include "InputChunks.h" -#include "InputEvent.h" -#include "InputGlobal.h" -#include "InputTable.h" +#include "InputElement.h" #include "OutputSegment.h" #include "SymbolTable.h" #include "lld/Common/ErrorHandler.h" diff --git a/lld/wasm/InputGlobal.h b/lld/wasm/InputGlobal.h deleted file mode 100644 --- a/lld/wasm/InputGlobal.h +++ /dev/null @@ -1,55 +0,0 @@ -//===- InputGlobal.h --------------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLD_WASM_INPUT_GLOBAL_H -#define LLD_WASM_INPUT_GLOBAL_H - -#include "Config.h" -#include "InputFiles.h" -#include "WriterUtils.h" -#include "lld/Common/ErrorHandler.h" -#include "llvm/Object/Wasm.h" - -namespace lld { -namespace wasm { - -// Represents a single Wasm Global Variable within an input file. These are -// combined to form the final GLOBALS section. -class InputGlobal { -public: - InputGlobal(const WasmGlobal &g, ObjFile *f) - : file(f), global(g), live(!config->gcSections) {} - - StringRef getName() const { return global.SymbolName; } - const WasmGlobalType &getType() const { return global.Type; } - - uint32_t getGlobalIndex() const { return globalIndex.getValue(); } - bool hasGlobalIndex() const { return globalIndex.hasValue(); } - void setGlobalIndex(uint32_t index) { - assert(!hasGlobalIndex()); - globalIndex = index; - } - - ObjFile *file; - WasmGlobal global; - - bool live = false; - -protected: - llvm::Optional globalIndex; -}; - -} // namespace wasm - -inline std::string toString(const wasm::InputGlobal *g) { - return (toString(g->file) + ":(" + g->getName() + ")").str(); -} - -} // namespace lld - -#endif // LLD_WASM_INPUT_GLOBAL_H diff --git a/lld/wasm/InputTable.h b/lld/wasm/InputTable.h deleted file mode 100644 --- a/lld/wasm/InputTable.h +++ /dev/null @@ -1,60 +0,0 @@ -//===- InputTable.h --------------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLD_WASM_INPUT_TABLE_H -#define LLD_WASM_INPUT_TABLE_H - -#include "Config.h" -#include "InputFiles.h" -#include "WriterUtils.h" -#include "lld/Common/ErrorHandler.h" -#include "llvm/Object/Wasm.h" - -namespace lld { -namespace wasm { - -// Represents a single Wasm Table within an input file. These are combined to -// form the final TABLES section. -class InputTable { -public: - InputTable(const WasmTable &t, ObjFile *f) - : file(f), table(t), live(!config->gcSections) {} - - StringRef getName() const { return table.SymbolName; } - const WasmTableType &getType() const { return table.Type; } - - // Somewhat confusingly, we generally use the term "table index" to refer to - // the offset of a function in the well-known indirect function table. We - // refer to different tables instead by "table numbers". - uint32_t getTableNumber() const { return tableNumber.getValue(); } - bool hasTableNumber() const { return tableNumber.hasValue(); } - void setTableNumber(uint32_t n) { - assert(!hasTableNumber()); - tableNumber = n; - } - - void setLimits(const WasmLimits &limits) { table.Type.Limits = limits; } - - ObjFile *file; - WasmTable table; - - bool live = false; - -protected: - llvm::Optional tableNumber; -}; - -} // namespace wasm - -inline std::string toString(const wasm::InputTable *t) { - return (toString(t->file) + ":(" + t->getName() + ")").str(); -} - -} // namespace lld - -#endif // LLD_WASM_INPUT_TABLE_H diff --git a/lld/wasm/MapFile.cpp b/lld/wasm/MapFile.cpp --- a/lld/wasm/MapFile.cpp +++ b/lld/wasm/MapFile.cpp @@ -19,8 +19,8 @@ //===----------------------------------------------------------------------===// #include "MapFile.h" +#include "InputElement.h" #include "InputFiles.h" -#include "InputGlobal.h" #include "OutputSections.h" #include "OutputSegment.h" #include "SymbolTable.h" @@ -148,7 +148,7 @@ } } else if (auto *globals = dyn_cast(osec)) { for (auto *global : globals->inputGlobals) { - writeHeader(os, global->getGlobalIndex(), 0, 0); + writeHeader(os, global->getAssignedIndex(), 0, 0); os.indent(8) << global->getName() << '\n'; } } diff --git a/lld/wasm/MarkLive.cpp b/lld/wasm/MarkLive.cpp --- a/lld/wasm/MarkLive.cpp +++ b/lld/wasm/MarkLive.cpp @@ -21,9 +21,7 @@ #include "MarkLive.h" #include "Config.h" #include "InputChunks.h" -#include "InputEvent.h" -#include "InputGlobal.h" -#include "InputTable.h" +#include "InputElement.h" #include "SymbolTable.h" #include "Symbols.h" diff --git a/lld/wasm/SymbolTable.cpp b/lld/wasm/SymbolTable.cpp --- a/lld/wasm/SymbolTable.cpp +++ b/lld/wasm/SymbolTable.cpp @@ -9,9 +9,7 @@ #include "SymbolTable.h" #include "Config.h" #include "InputChunks.h" -#include "InputEvent.h" -#include "InputGlobal.h" -#include "InputTable.h" +#include "InputElement.h" #include "WriterUtils.h" #include "lld/Common/ErrorHandler.h" #include "lld/Common/Memory.h" diff --git a/lld/wasm/Symbols.cpp b/lld/wasm/Symbols.cpp --- a/lld/wasm/Symbols.cpp +++ b/lld/wasm/Symbols.cpp @@ -9,10 +9,8 @@ #include "Symbols.h" #include "Config.h" #include "InputChunks.h" -#include "InputEvent.h" +#include "InputElement.h" #include "InputFiles.h" -#include "InputGlobal.h" -#include "InputTable.h" #include "OutputSections.h" #include "OutputSegment.h" #include "lld/Common/ErrorHandler.h" @@ -303,7 +301,7 @@ uint32_t GlobalSymbol::getGlobalIndex() const { if (auto *f = dyn_cast(this)) - return f->global->getGlobalIndex(); + return f->global->getAssignedIndex(); assert(globalIndex != INVALID_INDEX); return globalIndex; } @@ -316,7 +314,7 @@ bool GlobalSymbol::hasGlobalIndex() const { if (auto *f = dyn_cast(this)) - return f->global->hasGlobalIndex(); + return f->global->hasAssignedIndex(); return globalIndex != INVALID_INDEX; } @@ -328,7 +326,7 @@ uint32_t EventSymbol::getEventIndex() const { if (auto *f = dyn_cast(this)) - return f->event->getEventIndex(); + return f->event->getAssignedIndex(); assert(eventIndex != INVALID_INDEX); return eventIndex; } @@ -341,7 +339,7 @@ bool EventSymbol::hasEventIndex() const { if (auto *f = dyn_cast(this)) - return f->event->hasEventIndex(); + return f->event->hasAssignedIndex(); return eventIndex != INVALID_INDEX; } @@ -362,7 +360,7 @@ uint32_t TableSymbol::getTableNumber() const { if (const auto *t = dyn_cast(this)) - return t->table->getTableNumber(); + return t->table->getAssignedIndex(); assert(tableNumber != INVALID_INDEX); return tableNumber; } @@ -375,7 +373,7 @@ bool TableSymbol::hasTableNumber() const { if (const auto *t = dyn_cast(this)) - return t->table->hasTableNumber(); + return t->table->hasAssignedIndex(); return tableNumber != INVALID_INDEX; } diff --git a/lld/wasm/SyntheticSections.cpp b/lld/wasm/SyntheticSections.cpp --- a/lld/wasm/SyntheticSections.cpp +++ b/lld/wasm/SyntheticSections.cpp @@ -13,9 +13,7 @@ #include "SyntheticSections.h" #include "InputChunks.h" -#include "InputEvent.h" -#include "InputGlobal.h" -#include "InputTable.h" +#include "InputElement.h" #include "OutputSegment.h" #include "SymbolTable.h" #include "llvm/Support/Path.h" @@ -223,7 +221,7 @@ uint32_t tableNumber = out.importSec->getNumImportedTables() + inputTables.size(); inputTables.push_back(table); - table->setTableNumber(tableNumber); + table->assignIndex(tableNumber); } void MemorySection::writeBody() { @@ -249,8 +247,9 @@ writeUleb128(os, inputEvents.size(), "event count"); for (InputEvent *e : inputEvents) { - e->event.Type.SigIndex = out.typeSec->lookupType(e->signature); - writeEvent(os, e->event); + WasmEventType type = e->getType(); + type.SigIndex = out.typeSec->lookupType(e->signature); + writeEventType(os, type); } } @@ -260,14 +259,14 @@ uint32_t eventIndex = out.importSec->getNumImportedEvents() + inputEvents.size(); LLVM_DEBUG(dbgs() << "addEvent: " << eventIndex << "\n"); - event->setEventIndex(eventIndex); + event->assignIndex(eventIndex); inputEvents.push_back(event); } void GlobalSection::assignIndexes() { uint32_t globalIndex = out.importSec->getNumImportedGlobals(); for (InputGlobal *g : inputGlobals) - g->setGlobalIndex(globalIndex++); + g->assignIndex(globalIndex++); for (Symbol *sym : internalGotSymbols) sym->setGOTIndex(globalIndex++); isSealed = true; @@ -326,33 +325,37 @@ raw_ostream &os = bodyOutputStream; writeUleb128(os, numGlobals(), "global count"); - for (InputGlobal *g : inputGlobals) - writeGlobal(os, g->global); + for (InputGlobal *g : inputGlobals) { + writeGlobalType(os, g->getType()); + writeInitExpr(os, g->getInitExpr()); + } // TODO(wvo): when do these need I64_CONST? for (const Symbol *sym : internalGotSymbols) { - WasmGlobal global; // In the case of dynamic linking, internal GOT entries // need to be mutable since they get updated to the correct // runtime value during `__wasm_apply_global_relocs`. bool mutable_ = config->isPic & !sym->isStub; - global.Type = {WASM_TYPE_I32, mutable_}; - global.InitExpr.Opcode = WASM_OPCODE_I32_CONST; + WasmGlobalType type{WASM_TYPE_I32, mutable_}; + WasmInitExpr initExpr; + initExpr.Opcode = WASM_OPCODE_I32_CONST; if (auto *d = dyn_cast(sym)) - global.InitExpr.Value.Int32 = d->getVirtualAddress(); + initExpr.Value.Int32 = d->getVirtualAddress(); else if (auto *f = dyn_cast(sym)) - global.InitExpr.Value.Int32 = f->isStub ? 0 : f->getTableIndex(); + initExpr.Value.Int32 = f->isStub ? 0 : f->getTableIndex(); else { assert(isa(sym)); - global.InitExpr.Value.Int32 = 0; + initExpr.Value.Int32 = 0; } - writeGlobal(os, global); + writeGlobalType(os, type); + writeInitExpr(os, initExpr); } for (const DefinedData *sym : dataAddressGlobals) { - WasmGlobal global; - global.Type = {WASM_TYPE_I32, false}; - global.InitExpr.Opcode = WASM_OPCODE_I32_CONST; - global.InitExpr.Value.Int32 = sym->getVirtualAddress(); - writeGlobal(os, global); + WasmGlobalType type{WASM_TYPE_I32, false}; + WasmInitExpr initExpr; + initExpr.Opcode = WASM_OPCODE_I32_CONST; + initExpr.Value.Int32 = sym->getVirtualAddress(); + writeGlobalType(os, type); + writeInitExpr(os, initExpr); } } @@ -623,7 +626,7 @@ } for (const InputGlobal *g : out.globalSec->inputGlobals) { if (!g->getName().empty()) { - writeUleb128(sub.os, g->getGlobalIndex(), "global index"); + writeUleb128(sub.os, g->getAssignedIndex(), "global index"); writeStr(sub.os, maybeDemangleSymbol(g->getName()), "symbol name"); } } diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp --- a/lld/wasm/Writer.cpp +++ b/lld/wasm/Writer.cpp @@ -9,9 +9,7 @@ #include "Writer.h" #include "Config.h" #include "InputChunks.h" -#include "InputEvent.h" -#include "InputGlobal.h" -#include "InputTable.h" +#include "InputElement.h" #include "MapFile.h" #include "OutputSections.h" #include "OutputSegment.h" @@ -212,13 +210,7 @@ } static void setGlobalPtr(DefinedGlobal *g, uint64_t memoryPtr) { - if (config->is64.getValueOr(false)) { - assert(g->global->global.InitExpr.Opcode == WASM_OPCODE_I64_CONST); - g->global->global.InitExpr.Value.Int64 = memoryPtr; - } else { - assert(g->global->global.InitExpr.Opcode == WASM_OPCODE_I32_CONST); - g->global->global.InitExpr.Value.Int32 = memoryPtr; - } + g->global->setPointerValue(memoryPtr); } // Fix the memory layout of the output binary. This assigns memory offsets @@ -246,17 +238,7 @@ log("mem: stack size = " + Twine(config->zStackSize)); log("mem: stack base = " + Twine(memoryPtr)); memoryPtr += config->zStackSize; - auto *sp = cast(WasmSym::stackPointer); - switch (sp->global->global.InitExpr.Opcode) { - case WASM_OPCODE_I32_CONST: - sp->global->global.InitExpr.Value.Int32 = memoryPtr; - break; - case WASM_OPCODE_I64_CONST: - sp->global->global.InitExpr.Value.Int64 = memoryPtr; - break; - default: - llvm_unreachable("init expr must be i32/i64.const"); - } + setGlobalPtr(cast(WasmSym::stackPointer), memoryPtr); log("mem: stack top = " + Twine(memoryPtr)); }; diff --git a/lld/wasm/WriterUtils.h b/lld/wasm/WriterUtils.h --- a/lld/wasm/WriterUtils.h +++ b/lld/wasm/WriterUtils.h @@ -51,8 +51,6 @@ void writeGlobalType(raw_ostream &os, const llvm::wasm::WasmGlobalType &type); -void writeGlobal(raw_ostream &os, const llvm::wasm::WasmGlobal &global); - void writeEventType(raw_ostream &os, const llvm::wasm::WasmEventType &type); void writeEvent(raw_ostream &os, const llvm::wasm::WasmEvent &event); diff --git a/lld/wasm/WriterUtils.cpp b/lld/wasm/WriterUtils.cpp --- a/lld/wasm/WriterUtils.cpp +++ b/lld/wasm/WriterUtils.cpp @@ -202,11 +202,6 @@ writeU8(os, type.Mutable, "global mutable"); } -void writeGlobal(raw_ostream &os, const WasmGlobal &global) { - writeGlobalType(os, global.Type); - writeInitExpr(os, global.InitExpr); -} - void writeEventType(raw_ostream &os, const WasmEventType &type) { writeUleb128(os, type.Attribute, "event attribute"); writeUleb128(os, type.SigIndex, "sig index");