diff options
author | Derek Schuff <dschuff@chromium.org> | 2016-04-27 09:18:37 -0700 |
---|---|---|
committer | Derek Schuff <dschuff@chromium.org> | 2016-04-27 09:18:37 -0700 |
commit | d63486d0ef085f905dafdb14a76cfb2ca1fb452e (patch) | |
tree | 33fd133e9c3313c458ae756f0e7b397dfb198d28 /src/wasm-linker.h | |
parent | 206338a6c4e3f9739abd7a2ad082d1770b3a628f (diff) | |
download | binaryen-d63486d0ef085f905dafdb14a76cfb2ca1fb452e.tar.gz binaryen-d63486d0ef085f905dafdb14a76cfb2ca1fb452e.tar.bz2 binaryen-d63486d0ef085f905dafdb14a76cfb2ca1fb452e.zip |
Split construction, scanning, and building phases of S2WasmBuilder (#400)
Instead of doing all of the S2Wasm work in the constructor, split
construction, scanning (to determine implemented functions) and building
of the wasm module.
This allows the linker to get the symbol information (e.g. implemented
functions) without having to build an entire module (which will be
useful for archives) and to allow the linker to link a new object into
the existing one by building the wasm module in place on the existing
module.
Diffstat (limited to 'src/wasm-linker.h')
-rw-r--r-- | src/wasm-linker.h | 48 |
1 files changed, 34 insertions, 14 deletions
diff --git a/src/wasm-linker.h b/src/wasm-linker.h index e72f862f1..ab336e581 100644 --- a/src/wasm-linker.h +++ b/src/wasm-linker.h @@ -29,6 +29,8 @@ namespace wasm { +class S2WasmBuilder; + // An "object file" for linking. Contains a wasm module, plus the associated // information needed for linking/layout. class LinkerObject { @@ -44,6 +46,26 @@ class LinkerObject { Relocation(Kind kind, uint32_t* data, Name symbol, int addend) : kind(kind), data(data), symbol(symbol), addend(addend) {} }; + // Information about symbols + struct SymbolInfo { + std::unordered_set<cashew::IString> implementedFunctions; + std::unordered_set<cashew::IString> undefinedFunctions; + // TODO: it's not clear that this really belongs here. + std::unordered_map<cashew::IString, Name> aliasedFunctions; + + // For now, do not support weak symbols or anything special. Just directly + // merge the functions together, and remove any newly-defined functions + // from undefinedFunction + void merge(SymbolInfo&& other) { + for (const auto& func : other.implementedFunctions) { + undefinedFunctions.erase(func); + } + implementedFunctions.insert(other.implementedFunctions.begin(), + other.implementedFunctions.end()); + aliasedFunctions.insert(other.aliasedFunctions.begin(), + other.aliasedFunctions.end()); + } + }; LinkerObject() {} @@ -63,20 +85,15 @@ class LinkerObject { return relocations.back().get(); } - void addImplementedFunction(Name name) { - implementedFunctions.insert(name); - } + bool isFunctionImplemented(Name name) { - return implementedFunctions.count(name) != 0; + return symbolInfo.implementedFunctions.count(name) != 0; } - void addAliasedFunction(Name name, Name alias) { - aliasedFunctions.insert({name, alias}); - } // If name is an alias, return what it points to. Otherwise return name Name resolveAlias(Name name) { - auto aliased = aliasedFunctions.find(name); - if (aliased != aliasedFunctions.end()) return aliased->second; + auto aliased = symbolInfo.aliasedFunctions.find(name); + if (aliased != symbolInfo.aliasedFunctions.end()) return aliased->second; return name; } @@ -88,11 +105,12 @@ class LinkerObject { void addInitializerFunction(Name name) { initializerFunctions.emplace_back(name); - assert(implementedFunctions.count(name)); + assert(symbolInfo.implementedFunctions.count(name)); } void addUndefinedFunctionCall(Call* call) { - undefinedFunctions[call->target].push_back(call); + symbolInfo.undefinedFunctions.insert(call->target); + undefinedFunctionCalls[call->target].push_back(call); } bool isEmpty() { @@ -117,11 +135,10 @@ class LinkerObject { std::vector<StaticObject> staticObjects; std::vector<std::unique_ptr<Relocation>> relocations; - std::set<Name> implementedFunctions; - std::unordered_map<cashew::IString, Name> aliasedFunctions; + SymbolInfo symbolInfo; using CallList = std::vector<Call*>; - std::map<Name, CallList> undefinedFunctions; + std::map<Name, CallList> undefinedFunctionCalls; std::map<Name, size_t> segments; // name => segment index (in wasm module) @@ -187,6 +204,9 @@ class Linker { // metadata for asmConsts, staticBump and initializer functions. void emscriptenGlue(std::ostream& o); + // Add an object to the link by constructing it in-place with a builder. + bool linkObject(S2WasmBuilder& builder); + private: // Allocate a static variable and return its address in linear memory size_t allocateStatic(size_t allocSize, size_t alignment, Name name) { |