summaryrefslogtreecommitdiff
path: root/src/wasm-linker.h
diff options
context:
space:
mode:
authorDerek Schuff <dschuff@chromium.org>2016-04-27 09:18:37 -0700
committerDerek Schuff <dschuff@chromium.org>2016-04-27 09:18:37 -0700
commitd63486d0ef085f905dafdb14a76cfb2ca1fb452e (patch)
tree33fd133e9c3313c458ae756f0e7b397dfb198d28 /src/wasm-linker.h
parent206338a6c4e3f9739abd7a2ad082d1770b3a628f (diff)
downloadbinaryen-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.h48
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) {