summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/asm2wasm.h2
-rw-r--r--src/asmjs/CMakeLists.txt1
-rw-r--r--src/asmjs/shared-constants.cpp (renamed from src/shared-constants.h)9
-rw-r--r--src/asmjs/shared-constants.h104
-rw-r--r--src/parsing.h4
-rw-r--r--src/s2wasm-main.cpp8
-rw-r--r--src/s2wasm.h109
-rw-r--r--src/shell-interface.h3
-rw-r--r--src/wasm-binary.h2
-rw-r--r--src/wasm-linker.cpp36
-rw-r--r--src/wasm-linker.h48
-rw-r--r--src/wasm-s-parser.h2
-rw-r--r--src/wasm2asm.h2
13 files changed, 250 insertions, 80 deletions
diff --git a/src/asm2wasm.h b/src/asm2wasm.h
index 1da59d2f2..ae24358d7 100644
--- a/src/asm2wasm.h
+++ b/src/asm2wasm.h
@@ -25,7 +25,7 @@
#include "wasm.h"
#include "emscripten-optimizer/optimizer.h"
#include "mixed_arena.h"
-#include "shared-constants.h"
+#include "asmjs/shared-constants.h"
#include "asm_v_wasm.h"
#include "pass.h"
#include "ast_utils.h"
diff --git a/src/asmjs/CMakeLists.txt b/src/asmjs/CMakeLists.txt
index 8be8ea2c4..2387d3ca0 100644
--- a/src/asmjs/CMakeLists.txt
+++ b/src/asmjs/CMakeLists.txt
@@ -1,4 +1,5 @@
SET(asmjs_SOURCES
asm_v_wasm.cpp
+ shared-constants.cpp
)
ADD_LIBRARY(asmjs STATIC ${asmjs_SOURCES}) \ No newline at end of file
diff --git a/src/shared-constants.h b/src/asmjs/shared-constants.cpp
index 626c5423e..bc1c0fa3d 100644
--- a/src/shared-constants.h
+++ b/src/asmjs/shared-constants.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2015 WebAssembly Community Group participants
+ * Copyright 2016 WebAssembly Community Group participants
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,10 +14,7 @@
* limitations under the License.
*/
-#ifndef wasm_shared_constants_h
-#define wasm_shared_constants_h
-
-#include "emscripten-optimizer/optimizer.h"
+#include "asmjs/shared-constants.h"
namespace wasm {
@@ -100,5 +97,3 @@ cashew::IString GLOBAL("global"),
EXIT("exit");
}
-
-#endif // wasm_shared_constants_h
diff --git a/src/asmjs/shared-constants.h b/src/asmjs/shared-constants.h
new file mode 100644
index 000000000..2f6c608ba
--- /dev/null
+++ b/src/asmjs/shared-constants.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2015 WebAssembly Community Group participants
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef wasm_asmjs_shared_constants_h
+#define wasm_asmjs_shared_constants_h
+
+#include "emscripten-optimizer/istring.h"
+
+namespace wasm {
+
+extern cashew::IString GLOBAL,
+ NAN_,
+ INFINITY_,
+ NAN__,
+ INFINITY__,
+ TOPMOST,
+ INT8ARRAY,
+ INT16ARRAY,
+ INT32ARRAY,
+ UINT8ARRAY,
+ UINT16ARRAY,
+ UINT32ARRAY,
+ FLOAT32ARRAY,
+ FLOAT64ARRAY,
+ IMPOSSIBLE_CONTINUE,
+ MATH,
+ IMUL,
+ CLZ32,
+ FROUND,
+ ASM2WASM,
+ F64_REM,
+ F64_TO_INT,
+ GLOBAL_MATH,
+ ABS,
+ FLOOR,
+ CEIL,
+ SQRT,
+ I32_TEMP,
+ DEBUGGER,
+ GROW_WASM_MEMORY,
+ NEW_SIZE,
+ MODULE,
+ START,
+ FUNC,
+ PARAM,
+ RESULT,
+ MEMORY,
+ SEGMENT,
+ EXPORT,
+ IMPORT,
+ TABLE,
+ LOCAL,
+ TYPE,
+ CALL,
+ CALL_IMPORT,
+ CALL_INDIRECT,
+ BLOCK,
+ BR_IF,
+ THEN,
+ ELSE,
+ NEG_INFINITY,
+ NEG_NAN,
+ CASE,
+ BR,
+ USE_ASM,
+ BUFFER,
+ ENV,
+ FAKE_RETURN,
+ MATH_IMUL,
+ MATH_CLZ32,
+ MATH_CTZ32,
+ MATH_POPCNT32,
+ MATH_ABS,
+ MATH_CEIL,
+ MATH_FLOOR,
+ MATH_TRUNC,
+ MATH_NEAREST,
+ MATH_SQRT,
+ MATH_MIN,
+ MATH_MAX,
+ ASSERT_RETURN,
+ ASSERT_TRAP,
+ ASSERT_INVALID,
+ SPECTEST,
+ PRINT,
+ INVOKE,
+ EXIT;
+
+}
+
+#endif // wasm_asmjs_shared_constants_h
diff --git a/src/parsing.h b/src/parsing.h
index 935750537..2104337a6 100644
--- a/src/parsing.h
+++ b/src/parsing.h
@@ -19,14 +19,14 @@
#include <sstream>
+#include "asmjs/shared-constants.h"
#include "mixed_arena.h"
-#include "shared-constants.h"
#include "support/utilities.h"
#include "wasm.h"
namespace wasm {
-Expression* parseConst(cashew::IString s, WasmType type, MixedArena& allocator) {
+inline Expression* parseConst(cashew::IString s, WasmType type, MixedArena& allocator) {
const char *str = s.str;
auto ret = allocator.alloc<Const>();
ret->type = type;
diff --git a/src/s2wasm-main.cpp b/src/s2wasm-main.cpp
index 435eb560f..7b0e4c179 100644
--- a/src/s2wasm-main.cpp
+++ b/src/s2wasm-main.cpp
@@ -104,7 +104,13 @@ int main(int argc, const char *argv[]) {
Linker linker(globalBase, stackAllocation, initialMem, maxMem,
ignoreUnknownSymbols, startFunction, options.debug);
- S2WasmBuilder s2wasm(linker.getOutput(), input.c_str(), options.debug);
+ S2WasmBuilder mainbuilder(input.c_str(), options.debug);
+ linker.linkObject(mainbuilder);
+
+ // In the future, there will be code to open additional files/buffers and
+ // link additional objects, as well as archive members (which only get linked if needed), e.g.:
+ // S2WasmBuilder lazyObject(some_other_buffer, options.debug)
+ // linker.linkLazyObject(lazyObject); // calls builder.scan to get symbol info, then build
linker.layout();
diff --git a/src/s2wasm.h b/src/s2wasm.h
index 00e6b12a2..b66859ce9 100644
--- a/src/s2wasm.h
+++ b/src/s2wasm.h
@@ -37,26 +37,40 @@ namespace wasm {
//
class S2WasmBuilder {
- Module& wasm;
- MixedArena& allocator;
+ const char* inputStart;
const char* s;
bool debug;
- LinkerObject& linkerObj;
+ Module* wasm;
+ MixedArena* allocator;
+ LinkerObject* linkerObj;
public:
- S2WasmBuilder(LinkerObject& linkerObj, const char* input, bool debug)
- : wasm(linkerObj.wasm),
- allocator(wasm.allocator),
+ S2WasmBuilder(const char* input, bool debug)
+ : inputStart(input),
+ s(input),
debug(debug),
- linkerObj(linkerObj) {
- if (!linkerObj.isEmpty()) Fatal() << "Cannot construct an S2WasmBuilder in an non-empty LinkerObject";
- s = input;
- scan();
- s = input;
+ wasm(nullptr),
+ allocator(nullptr),
+ linkerObj(nullptr)
+ {}
+ void build(LinkerObject *obj, LinkerObject::SymbolInfo* info) {
+ if (!obj->isEmpty()) Fatal() << "Cannot construct an S2WasmBuilder in an non-empty LinkerObject";
+ if (!info) info = getSymbolInfo();
+ linkerObj = obj;
+ wasm = &obj->wasm;
+ allocator = &wasm->allocator;
+
+ s = inputStart;
process();
}
+ LinkerObject::SymbolInfo* getSymbolInfo() {
+ auto* info = new LinkerObject::SymbolInfo();
+ scan(info);
+ return info;
+ }
+
private:
// utilities
@@ -209,7 +223,7 @@ class S2WasmBuilder {
s++;
offset = -getInt();
}
- linkerObj.addRelocation(kind, target, cleanFunction(name), offset);
+ linkerObj->addRelocation(kind, target, cleanFunction(name), offset);
return true;
}
}
@@ -334,7 +348,8 @@ class S2WasmBuilder {
// processors
- void scan() {
+ void scan(LinkerObject::SymbolInfo* info) {
+ s = inputStart;
while (*s) {
skipWhitespace();
s = strstr(s, ".type");
@@ -346,11 +361,11 @@ class S2WasmBuilder {
if (match(".hidden")) mustMatch(name.str);
mustMatch(name.str);
if (match(":")) {
- linkerObj.addImplementedFunction(name);
+ info->implementedFunctions.insert(name);
} else if (match("=")) {
Name alias = getAtSeparated();
mustMatch("@FUNCTION");
- linkerObj.addAliasedFunction(name, alias);
+ info->aliasedFunctions.insert({name, alias});
} else {
abort_on("unknown directive");
}
@@ -402,7 +417,7 @@ class S2WasmBuilder {
}
mustMatch(".int32");
do {
- linkerObj.addInitializerFunction(cleanFunction(getStr()));
+ linkerObj->addInitializerFunction(cleanFunction(getStr()));
skipWhitespace();
} while (match(".int32"));
}
@@ -437,7 +452,7 @@ class S2WasmBuilder {
}
void parseGlobl() {
- linkerObj.addGlobal(getStr());
+ linkerObj->addGlobal(getStr());
skipWhitespace();
}
@@ -465,7 +480,7 @@ class S2WasmBuilder {
auto getNextId = [&nextId]() {
return cashew::IString(('$' + std::to_string(nextId++)).c_str(), false);
};
- wasm::Builder builder(wasm);
+ wasm::Builder builder(*wasm);
std::vector<NameType> params;
WasmType resultType = none;
std::vector<NameType> vars;
@@ -498,7 +513,7 @@ class S2WasmBuilder {
Function* func = builder.makeFunction(name, std::move(params), resultType, std::move(vars));
// parse body
- func->body = allocator.alloc<Block>();
+ func->body = allocator->alloc<Block>();
std::vector<Expression*> bstack;
auto addToBlock = [&bstack](Expression* curr) {
Expression* last = bstack.back();
@@ -543,7 +558,7 @@ class S2WasmBuilder {
skipToSep();
inputs[i] = nullptr;
} else {
- auto curr = allocator.alloc<GetLocal>();
+ auto curr = allocator->alloc<GetLocal>();
curr->index = func->getLocalIndex(getStrToSep());
curr->type = func->getLocalType(curr->index);
inputs[i] = curr;
@@ -569,7 +584,7 @@ class S2WasmBuilder {
} else if (assign.str[1] == 'p') { // push
push(curr);
} else { // set to a local
- auto set = allocator.alloc<SetLocal>();
+ auto set = allocator->alloc<SetLocal>();
set->index = func->getLocalIndex(assign);
set->value = curr;
set->type = curr->type;
@@ -597,7 +612,7 @@ class S2WasmBuilder {
auto makeBinary = [&](BinaryOp op, WasmType type) {
Name assign = getAssign();
skipComma();
- auto curr = allocator.alloc<Binary>();
+ auto curr = allocator->alloc<Binary>();
curr->op = op;
auto inputs = getInputs(2);
curr->left = inputs[0];
@@ -609,7 +624,7 @@ class S2WasmBuilder {
auto makeUnary = [&](UnaryOp op, WasmType type) {
Name assign = getAssign();
skipComma();
- auto curr = allocator.alloc<Unary>();
+ auto curr = allocator->alloc<Unary>();
curr->op = op;
curr->value = getInput();
curr->type = type;
@@ -617,20 +632,20 @@ class S2WasmBuilder {
};
auto makeHost = [&](HostOp op) {
Name assign = getAssign();
- auto curr = allocator.alloc<Host>();
+ auto curr = allocator->alloc<Host>();
curr->op = op;
setOutput(curr, assign);
};
auto makeHost1 = [&](HostOp op) {
Name assign = getAssign();
- auto curr = allocator.alloc<Host>();
+ auto curr = allocator->alloc<Host>();
curr->op = op;
curr->operands.push_back(getInput());
setOutput(curr, assign);
};
auto makeLoad = [&](WasmType type) {
skipComma();
- auto curr = allocator.alloc<Load>();
+ auto curr = allocator->alloc<Load>();
curr->type = type;
int32_t bytes = getInt() / CHAR_BIT;
curr->bytes = bytes > 0 ? bytes : getWasmTypeSize(type);
@@ -650,7 +665,7 @@ class S2WasmBuilder {
};
auto makeStore = [&](WasmType type) {
skipComma();
- auto curr = allocator.alloc<Store>();
+ auto curr = allocator->alloc<Store>();
curr->type = type;
int32_t bytes = getInt() / CHAR_BIT;
curr->bytes = bytes > 0 ? bytes : getWasmTypeSize(type);
@@ -671,7 +686,7 @@ class S2WasmBuilder {
auto makeSelect = [&](WasmType type) {
Name assign = getAssign();
skipComma();
- auto curr = allocator.alloc<Select>();
+ auto curr = allocator->alloc<Select>();
auto inputs = getInputs(3);
curr->ifTrue = inputs[0];
curr->ifFalse = inputs[1];
@@ -689,7 +704,7 @@ class S2WasmBuilder {
auto input = inputs.begin();
auto* target = *input;
std::vector<Expression*> operands(++input, inputs.end());
- auto* funcType = ensureFunctionType(getSig(type, operands), &wasm);
+ auto* funcType = ensureFunctionType(getSig(type, operands), wasm);
assert(type == funcType->result);
auto* indirect = builder.makeCallIndirect(funcType, target, std::move(operands));
setOutput(indirect, assign);
@@ -697,13 +712,13 @@ class S2WasmBuilder {
} else {
// non-indirect call
Name assign = getAssign();
- Name target = linkerObj.resolveAlias(cleanFunction(getCommaSeparated()));
+ Name target = linkerObj->resolveAlias(cleanFunction(getCommaSeparated()));
- Call* curr = allocator.alloc<Call>();
+ Call* curr = allocator->alloc<Call>();
curr->target = target;
curr->type = type;
- if (!linkerObj.isFunctionImplemented(target)) {
- linkerObj.addUndefinedFunctionCall(curr);
+ if (!linkerObj->isFunctionImplemented(target)) {
+ linkerObj->addUndefinedFunctionCall(curr);
}
skipWhitespace();
if (*s == ',') {
@@ -731,13 +746,13 @@ class S2WasmBuilder {
Name assign = getAssign();
if (type == i32) {
// may be a relocation
- auto curr = allocator.alloc<Const>();
+ auto curr = allocator->alloc<Const>();
curr->type = curr->value.type = i32;
getConst((uint32_t*)curr->value.geti32Ptr());
setOutput(curr, assign);
} else {
cashew::IString str = getStr();
- setOutput(parseConst(str, type, allocator), assign);
+ setOutput(parseConst(str, type, *allocator), assign);
}
}
else if (match("call")) makeCall(type);
@@ -891,7 +906,7 @@ class S2WasmBuilder {
} else if (match("f64.")) {
handleTyped(f64);
} else if (match("block")) {
- auto curr = allocator.alloc<Block>();
+ auto curr = allocator->alloc<Block>();
curr->name = getNextLabel();
addToBlock(curr);
bstack.push_back(curr);
@@ -900,11 +915,11 @@ class S2WasmBuilder {
} else if (match(".LBB")) {
s = strchr(s, '\n');
} else if (match("loop")) {
- auto curr = allocator.alloc<Loop>();
+ auto curr = allocator->alloc<Loop>();
addToBlock(curr);
curr->in = getNextLabel();
curr->out = getNextLabel();
- auto block = allocator.alloc<Block>();
+ auto block = allocator->alloc<Block>();
block->name = curr->out; // temporary, fake - this way, on bstack we have the right label at the right offset for a br
curr->body = block;
loopBlocks.push_back(block);
@@ -914,7 +929,7 @@ class S2WasmBuilder {
bstack.pop_back();
bstack.pop_back();
} else if (match("br_table")) {
- auto curr = allocator.alloc<Switch>();
+ auto curr = allocator->alloc<Switch>();
curr->condition = getInput();
while (skipComma()) {
curr->targets.push_back(getBranchLabel(getInt()));
@@ -924,7 +939,7 @@ class S2WasmBuilder {
curr->targets.pop_back();
addToBlock(curr);
} else if (match("br")) {
- auto curr = allocator.alloc<Break>();
+ auto curr = allocator->alloc<Break>();
bool hasCondition = false;
if (*s == '_') {
mustMatch("_if");
@@ -945,7 +960,7 @@ class S2WasmBuilder {
} else if (match("tee_local")) {
Name assign = getAssign();
skipComma();
- auto curr = allocator.alloc<SetLocal>();
+ auto curr = allocator->alloc<SetLocal>();
curr->index = func->getLocalIndex(getAssign());
skipComma();
curr->value = getInput();
@@ -954,7 +969,7 @@ class S2WasmBuilder {
} else if (match("return")) {
addToBlock(builder.makeReturn(*s == '$' ? getInput() : nullptr));
} else if (match("unreachable")) {
- addToBlock(allocator.alloc<Unreachable>());
+ addToBlock(allocator->alloc<Unreachable>());
} else if (match("memory_size")) {
makeHost(CurrentMemory);
} else if (match("grow_memory")) {
@@ -978,7 +993,7 @@ class S2WasmBuilder {
block->name = Name();
}
func->body->dynCast<Block>()->finalize();
- wasm.addFunction(func);
+ wasm->addFunction(func);
}
void parseType() {
@@ -1064,7 +1079,7 @@ class S2WasmBuilder {
size_t size = raw->size();
raw->resize(size + 4);
if (getConst((uint32_t*)&(*raw)[size])) { // just the size, as we may reallocate; we must fix this later, if it's a relocation
- currRelocations.emplace_back(linkerObj.getCurrentRelocation(), size);
+ currRelocations.emplace_back(linkerObj->getCurrentRelocation(), size);
}
zero = false;
} else if (match(".int64")) {
@@ -1095,9 +1110,9 @@ class S2WasmBuilder {
r->data = (uint32_t*)&(*raw)[i];
}
// assign the address, add to memory
- linkerObj.addStatic(size, align, name);
+ linkerObj->addStatic(size, align, name);
if (!zero) {
- linkerObj.addSegment(name, (const char*)&(*raw)[0], size);
+ linkerObj->addSegment(name, (const char*)&(*raw)[0], size);
}
}
@@ -1109,7 +1124,7 @@ class S2WasmBuilder {
skipComma();
getInt();
}
- linkerObj.addStatic(size, align, name);
+ linkerObj->addStatic(size, align, name);
}
void skipImports() {
diff --git a/src/shell-interface.h b/src/shell-interface.h
index daaf23501..b23b7b645 100644
--- a/src/shell-interface.h
+++ b/src/shell-interface.h
@@ -18,7 +18,7 @@
// Implementation of the shell interpreter execution environment
//
-#include "shared-constants.h"
+#include "asmjs/shared-constants.h"
#include "wasm.h"
#include "wasm-interpreter.h"
@@ -177,4 +177,3 @@ struct ShellExternalInterface : ModuleInstance::ExternalInterface {
};
}
-
diff --git a/src/wasm-binary.h b/src/wasm-binary.h
index d13e1a526..0cf85a50f 100644
--- a/src/wasm-binary.h
+++ b/src/wasm-binary.h
@@ -26,7 +26,7 @@
#include "wasm.h"
#include "wasm-traversal.h"
-#include "shared-constants.h"
+#include "asmjs/shared-constants.h"
#include "asm_v_wasm.h"
#include "wasm-builder.h"
#include "ast_utils.h"
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);
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) {
diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h
index e1a073b0b..b6a532790 100644
--- a/src/wasm-s-parser.h
+++ b/src/wasm-s-parser.h
@@ -27,8 +27,8 @@
#include <limits>
#include "wasm.h"
+#include "asmjs/shared-constants.h"
#include "mixed_arena.h"
-#include "shared-constants.h"
#include "parsing.h"
#include "asm_v_wasm.h"
#include "ast_utils.h"
diff --git a/src/wasm2asm.h b/src/wasm2asm.h
index 1c1dba6e1..82eb0b1a9 100644
--- a/src/wasm2asm.h
+++ b/src/wasm2asm.h
@@ -24,11 +24,11 @@
#include <cmath>
+#include "asmjs/shared-constants.h"
#include "wasm.h"
#include "emscripten-optimizer/optimizer.h"
#include "mixed_arena.h"
#include "asm_v_wasm.h"
-#include "shared-constants.h"
namespace wasm {