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.cpp | |
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.cpp')
-rw-r--r-- | src/wasm-linker.cpp | 36 |
1 files changed, 33 insertions, 3 deletions
diff --git a/src/wasm-linker.cpp b/src/wasm-linker.cpp index 8fc4f18c8..6dca9e01b 100644 --- a/src/wasm-linker.cpp +++ b/src/wasm-linker.cpp @@ -17,6 +17,7 @@ #include "wasm-linker.h" #include "asm_v_wasm.h" #include "ast_utils.h" +#include "s2wasm.h" #include "support/utilities.h" #include "wasm-builder.h" #include "wasm-printing.h" @@ -51,7 +52,7 @@ void Linker::placeStackPointer(size_t stackAllocation) { void Linker::layout() { // Convert calls to undefined functions to call_imports - for (const auto& f : out.undefinedFunctions) { + for (const auto& f : out.undefinedFunctionCalls) { Name target = f.first; // Create an import for the target if necessary. if (!out.wasm.checkImport(target)) { @@ -145,12 +146,12 @@ void Linker::layout() { } } if (!!startFunction) { - if (out.implementedFunctions.count(startFunction) == 0) { + if (out.symbolInfo.implementedFunctions.count(startFunction) == 0) { Fatal() << "Unknown start function: `" << startFunction << "`\n"; } const auto *target = out.wasm.getFunction(startFunction); Name start("_start"); - if (out.implementedFunctions.count(start) != 0) { + if (out.symbolInfo.implementedFunctions.count(start) != 0) { Fatal() << "Start function already present: `" << start << "`\n"; } auto* func = out.wasm.allocator.alloc<Function>(); @@ -186,6 +187,35 @@ void Linker::layout() { } } +bool Linker::linkObject(S2WasmBuilder& builder) { + LinkerObject::SymbolInfo *newSymbols = builder.getSymbolInfo(); + // check for multiple definitions + for (const Name& symbol : newSymbols->implementedFunctions) { + if (out.symbolInfo.implementedFunctions.count(symbol)) { + // TODO: Figure out error handling for library-style pieces + // TODO: give LinkerObjects (or builders) names for better errors. + std::cerr << "Error: multiple definition of symbol " << symbol << "\n"; + return false; + } + } + // Allow duplicate aliases only if they refer to the same name. For now we + // do not expect aliases in compiler-rt files. + // TODO: figure out what the semantics of merging aliases should be. + for (const auto& alias : newSymbols->aliasedFunctions) { + if (out.symbolInfo.aliasedFunctions.count(alias.first) && + out.symbolInfo.aliasedFunctions[alias.first] != alias.second) { + std::cerr << "Error: conflicting definitions for alias " + << alias.first.c_str() << "\n"; + return false; + } + } + out.symbolInfo.merge(std::move(*newSymbols)); + builder.build(&out, &out.symbolInfo); + delete newSymbols; + return true; +} + + void Linker::emscriptenGlue(std::ostream& o) { if (debug) { WasmPrinter::printModule(&out.wasm, std::cerr); |