summaryrefslogtreecommitdiff
path: root/src/wasm-linker.cpp
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.cpp
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.cpp')
-rw-r--r--src/wasm-linker.cpp36
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);