summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/s2wasm-main.cpp14
-rw-r--r--src/s2wasm.h41
-rw-r--r--src/wasm-linker.cpp89
-rw-r--r--src/wasm-linker.h168
4 files changed, 171 insertions, 141 deletions
diff --git a/src/s2wasm-main.cpp b/src/s2wasm-main.cpp
index c6a77c583..435eb560f 100644
--- a/src/s2wasm-main.cpp
+++ b/src/s2wasm-main.cpp
@@ -84,7 +84,6 @@ int main(int argc, const char *argv[]) {
auto input(read_file<std::string>(options.extra["infile"], Flags::Text, options.debug ? Flags::Debug : Flags::Release));
if (options.debug) std::cerr << "Parsing and wasming..." << std::endl;
- Module wasm;
uint64_t globalBase = options.extra.find("global-base") != options.extra.end()
? std::stoull(options.extra["global-base"])
: 0;
@@ -101,21 +100,24 @@ int main(int argc, const char *argv[]) {
? std::stoull(options.extra["max-memory"])
: 0;
if (options.debug) std::cerr << "Global base " << globalBase << '\n';
- Linker lm(wasm, globalBase, stackAllocation, initialMem, maxMem,
- ignoreUnknownSymbols, startFunction, options.debug);
- S2WasmBuilder s2wasm(wasm, input.c_str(), options.debug, lm);
+ Linker linker(globalBase, stackAllocation, initialMem, maxMem,
+ ignoreUnknownSymbols, startFunction, options.debug);
+
+ S2WasmBuilder s2wasm(linker.getOutput(), input.c_str(), options.debug);
+
+ linker.layout();
std::stringstream meta;
if (generateEmscriptenGlue) {
if (options.debug) std::cerr << "Emscripten gluing..." << std::endl;
// dyncall thunks
- lm.emscriptenGlue(meta);
+ linker.emscriptenGlue(meta);
}
if (options.debug) std::cerr << "Printing..." << std::endl;
Output output(options.extra["output"], Flags::Text, options.debug ? Flags::Debug : Flags::Release);
- WasmPrinter::printModule(&wasm, output.getStream());
+ WasmPrinter::printModule(&linker.getOutput().wasm, output.getStream());
output << meta.str() << std::endl;
if (options.debug) std::cerr << "Done." << std::endl;
diff --git a/src/s2wasm.h b/src/s2wasm.h
index 2e979f589..f70246d4f 100644
--- a/src/s2wasm.h
+++ b/src/s2wasm.h
@@ -41,23 +41,20 @@ class S2WasmBuilder {
MixedArena& allocator;
const char* s;
bool debug;
- Linker& linker;
+ LinkerObject& linkerObj;
public:
- S2WasmBuilder(Module& wasm, const char* input, bool debug,
- Linker& linker)
- : wasm(wasm),
+ S2WasmBuilder(LinkerObject& linkerObj, const char* input, bool debug)
+ : wasm(linkerObj.wasm),
allocator(wasm.allocator),
debug(debug),
- linker(linker) {
-
+ linkerObj(linkerObj) {
+ if (!linkerObj.isEmpty()) Fatal() << "Cannot construct an S2WasmBuilder in an non-empty LinkerObject";
s = input;
scan();
s = input;
process();
-
- linker.layout();
}
private:
@@ -201,7 +198,9 @@ class S2WasmBuilder {
} else {
// a global constant, we need to fix it up later
Name name = getStrToSep();
- Linker::Relocation::Kind kind = isFunctionName(name) ? Linker::Relocation::kFunction : Linker::Relocation::kData;
+ LinkerObject::Relocation::Kind kind = isFunctionName(name) ?
+ LinkerObject::Relocation::kFunction :
+ LinkerObject::Relocation::kData;
int offset = 0;
if (*s == '+') {
s++;
@@ -210,7 +209,7 @@ class S2WasmBuilder {
s++;
offset = -getInt();
}
- linker.addRelocation(kind, target, cleanFunction(name), offset);
+ linkerObj.addRelocation(kind, target, cleanFunction(name), offset);
return true;
}
}
@@ -347,11 +346,11 @@ class S2WasmBuilder {
if (match(".hidden")) mustMatch(name.str);
mustMatch(name.str);
if (match(":")) {
- linker.addImplementedFunction(name);
+ linkerObj.addImplementedFunction(name);
} else if (match("=")) {
Name alias = getAtSeparated();
mustMatch("@FUNCTION");
- linker.addAliasedFunction(name, alias);
+ linkerObj.addAliasedFunction(name, alias);
} else {
abort_on("unknown directive");
}
@@ -403,7 +402,7 @@ class S2WasmBuilder {
}
mustMatch(".int32");
do {
- linker.addInitializerFunction(cleanFunction(getStr()));
+ linkerObj.addInitializerFunction(cleanFunction(getStr()));
skipWhitespace();
} while (match(".int32"));
}
@@ -438,7 +437,7 @@ class S2WasmBuilder {
}
void parseGlobl() {
- linker.addGlobal(getStr());
+ linkerObj.addGlobal(getStr());
skipWhitespace();
}
@@ -699,8 +698,8 @@ class S2WasmBuilder {
// non-indirect call
CallBase* curr;
Name assign = getAssign();
- Name target = linker.resolveAlias(cleanFunction(getCommaSeparated()));
- if (linker.isFunctionImplemented(target)) {
+ Name target = linkerObj.resolveAlias(cleanFunction(getCommaSeparated()));
+ if (linkerObj.isFunctionImplemented(target)) {
auto specific = allocator.alloc<Call>();
specific->target = target;
curr = specific;
@@ -1037,7 +1036,7 @@ class S2WasmBuilder {
mustMatch(":");
auto raw = new std::vector<char>(); // leaked intentionally, no new allocation in Memory
bool zero = true;
- std::vector<std::pair<Linker::Relocation*, size_t>> currRelocations; // [relocation, offset in raw]
+ std::vector<std::pair<LinkerObject::Relocation*, size_t>> currRelocations; // [relocation, offset in raw]
while (1) {
skipWhitespace();
if (match(".asci")) {
@@ -1079,7 +1078,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(linker.getCurrentRelocation(), size);
+ currRelocations.emplace_back(linkerObj.getCurrentRelocation(), size);
}
zero = false;
} else if (match(".int64")) {
@@ -1110,9 +1109,9 @@ class S2WasmBuilder {
r->data = (uint32_t*)&(*raw)[i];
}
// assign the address, add to memory
- linker.addStatic(size, align, name);
+ linkerObj.addStatic(size, align, name);
if (!zero) {
- linker.addSegment(name, (const char*)&(*raw)[0], size);
+ linkerObj.addSegment(name, (const char*)&(*raw)[0], size);
}
}
@@ -1124,7 +1123,7 @@ class S2WasmBuilder {
skipComma();
getInt();
}
- linker.addStatic(size, align, name);
+ linkerObj.addStatic(size, align, name);
}
void skipImports() {
diff --git a/src/wasm-linker.cpp b/src/wasm-linker.cpp
index 2c5e0003d..2e5787670 100644
--- a/src/wasm-linker.cpp
+++ b/src/wasm-linker.cpp
@@ -37,26 +37,27 @@ void Linker::placeStackPointer(size_t stackAllocation) {
const size_t pointerSize = 4;
// Unconditionally allocate space for the stack pointer. Emscripten
// allocates the stack itself, and initializes the stack pointer itself.
- addStatic(pointerSize, pointerSize, "__stack_pointer");
+ out.addStatic(pointerSize, pointerSize, "__stack_pointer");
if (stackAllocation) {
// If we are allocating the stack, set up a relocation to initialize the
// stack pointer to point to one past-the-end of the stack allocation.
auto* raw = new uint32_t;
- addRelocation(Relocation::kData, raw, ".stack", stackAllocation);
- assert(wasm.memory.segments.size() == 0);
- addSegment("__stack_pointer", reinterpret_cast<char*>(raw), pointerSize);
+ out.addRelocation(LinkerObject::Relocation::kData, raw, ".stack", stackAllocation);
+ assert(out.wasm.memory.segments.size() == 0);
+ out.addSegment("__stack_pointer", reinterpret_cast<char*>(raw), pointerSize);
}
}
void Linker::layout() {
// Allocate all user statics
- for (const auto& obj : staticObjects) {
+ for (const auto& obj : out.staticObjects) {
allocateStatic(obj.allocSize, obj.alignment, obj.name);
}
+
// Update the segments with their addresses now that they have been allocated.
- for (auto& seg : segments) {
+ for (auto& seg : out.segments) {
size_t address = staticAddresses[seg.first];
- wasm.memory.segments[seg.second].offset = address;
+ out.wasm.memory.segments[seg.second].offset = address;
segmentsByAddress[address] = seg.second;
}
@@ -73,41 +74,41 @@ void Linker::layout() {
Fatal() << "Specified initial memory size " << userInitialMemory <<
" is smaller than required size " << initialMem;
}
- wasm.memory.initial = userInitialMemory / Memory::kPageSize;
+ out.wasm.memory.initial = userInitialMemory / Memory::kPageSize;
} else {
- wasm.memory.initial = initialMem / Memory::kPageSize;
+ out.wasm.memory.initial = initialMem / Memory::kPageSize;
}
- if (userMaxMemory) wasm.memory.max = userMaxMemory / Memory::kPageSize;
- wasm.memory.exportName = MEMORY;
+ if (userMaxMemory) out.wasm.memory.max = userMaxMemory / Memory::kPageSize;
+ out.wasm.memory.exportName = MEMORY;
// XXX For now, export all functions marked .globl.
- for (Name name : globls) exportFunction(name, false);
- for (Name name : initializerFunctions) exportFunction(name, true);
+ for (Name name : out.globls) exportFunction(name, false);
+ for (Name name : out.initializerFunctions) exportFunction(name, true);
auto ensureFunctionIndex = [this](Name name) {
if (functionIndexes.count(name) == 0) {
- functionIndexes[name] = wasm.table.names.size();
- wasm.table.names.push_back(name);
+ functionIndexes[name] = out.wasm.table.names.size();
+ out.wasm.table.names.push_back(name);
if (debug) {
std::cerr << "function index: " << name << ": "
<< functionIndexes[name] << '\n';
}
}
};
- for (auto& relocation : relocations) {
+ for (auto& relocation : out.relocations) {
Name name = relocation->symbol;
if (debug) std::cerr << "fix relocation " << name << '\n';
- if (relocation->kind == Relocation::kData) {
+ if (relocation->kind == LinkerObject::Relocation::kData) {
const auto& symbolAddress = staticAddresses.find(name);
assert(symbolAddress != staticAddresses.end());
*(relocation->data) = symbolAddress->second + relocation->addend;
if (debug) std::cerr << " ==> " << *(relocation->data) << '\n';
} else {
// function address
- name = resolveAlias(name);
- if (!wasm.checkFunction(name)) {
+ name = out.resolveAlias(name);
+ if (!out.wasm.checkFunction(name)) {
std::cerr << "Unknown symbol: " << name << '\n';
if (!ignoreUnknownSymbols) Fatal() << "undefined reference\n";
*(relocation->data) = 0;
@@ -118,31 +119,31 @@ void Linker::layout() {
}
}
if (!!startFunction) {
- if (implementedFunctions.count(startFunction) == 0) {
+ if (out.implementedFunctions.count(startFunction) == 0) {
Fatal() << "Unknown start function: `" << startFunction << "`\n";
}
- const auto *target = wasm.getFunction(startFunction);
+ const auto *target = out.wasm.getFunction(startFunction);
Name start("_start");
- if (implementedFunctions.count(start) != 0) {
+ if (out.implementedFunctions.count(start) != 0) {
Fatal() << "Start function already present: `" << start << "`\n";
}
- auto* func = wasm.allocator.alloc<Function>();
+ auto* func = out.wasm.allocator.alloc<Function>();
func->name = start;
- wasm.addFunction(func);
+ out.wasm.addFunction(func);
exportFunction(start, true);
- wasm.addStart(start);
- auto* block = wasm.allocator.alloc<Block>();
+ out.wasm.addStart(start);
+ auto* block = out.wasm.allocator.alloc<Block>();
func->body = block;
{
// Create the call, matching its parameters.
// TODO allow calling with non-default values.
- auto* call = wasm.allocator.alloc<Call>();
+ auto* call = out.wasm.allocator.alloc<Call>();
call->target = startFunction;
size_t paramNum = 0;
for (WasmType type : target->params) {
Name name = Name::fromInt(paramNum++);
Builder::addVar(func, name, type);
- auto* param = wasm.allocator.alloc<GetLocal>();
+ auto* param = out.wasm.allocator.alloc<GetLocal>();
param->index = func->getLocalIndex(name);
param->type = type;
call->operands.push_back(param);
@@ -153,18 +154,18 @@ void Linker::layout() {
}
// ensure an explicit function type for indirect call targets
- for (auto& name : wasm.table.names) {
- auto* func = wasm.getFunction(name);
- func->type = ensureFunctionType(getSig(func), &wasm, wasm.allocator)->name;
+ for (auto& name : out.wasm.table.names) {
+ auto* func = out.wasm.getFunction(name);
+ func->type = ensureFunctionType(getSig(func), &out.wasm, out.wasm.allocator)->name;
}
}
void Linker::emscriptenGlue(std::ostream& o) {
if (debug) {
- WasmPrinter::printModule(&wasm, std::cerr);
+ WasmPrinter::printModule(&out.wasm, std::cerr);
}
- wasm.removeImport(EMSCRIPTEN_ASM_CONST); // we create _sig versions
+ out.wasm.removeImport(EMSCRIPTEN_ASM_CONST); // we create _sig versions
makeDynCallThunks();
@@ -181,7 +182,7 @@ void Linker::emscriptenGlue(std::ostream& o) {
if (curr->target == EMSCRIPTEN_ASM_CONST) {
auto arg = curr->operands[0]->cast<Const>();
size_t segmentIndex = parent->segmentsByAddress[arg->value.geti32()];
- std::string code = escape(parent->wasm.memory.segments[segmentIndex].data);
+ std::string code = escape(parent->out.wasm.memory.segments[segmentIndex].data);
int32_t id;
if (ids.count(code) == 0) {
id = ids.size();
@@ -197,11 +198,11 @@ void Linker::emscriptenGlue(std::ostream& o) {
// add import, if necessary
if (allSigs.count(sig) == 0) {
allSigs.insert(sig);
- auto import = parent->wasm.allocator.alloc<Import>();
+ auto import = parent->out.wasm.allocator.alloc<Import>();
import->name = import->base = curr->target;
import->module = ENV;
- import->type = ensureFunctionType(getSig(curr), &parent->wasm, parent->wasm.allocator);
- parent->wasm.addImport(import);
+ import->type = ensureFunctionType(getSig(curr), &parent->out.wasm, parent->out.wasm.allocator);
+ parent->out.wasm.addImport(import);
}
}
}
@@ -230,7 +231,7 @@ void Linker::emscriptenGlue(std::ostream& o) {
};
AsmConstWalker walker;
walker.parent = this;
- walker.startWalk(&wasm);
+ walker.startWalk(&out.wasm);
// print
o << "\"asmConsts\": {";
bool first = true;
@@ -249,7 +250,7 @@ void Linker::emscriptenGlue(std::ostream& o) {
o << "\"initializers\": [";
first = true;
- for (const auto& func : initializerFunctions) {
+ for (const auto& func : out.initializerFunctions) {
if (first) first = false;
else o << ", ";
o << "\"" << func.c_str() << "\"";
@@ -261,10 +262,10 @@ void Linker::emscriptenGlue(std::ostream& o) {
void Linker::makeDynCallThunks() {
std::unordered_set<std::string> sigs;
- wasm::Builder wasmBuilder(wasm);
- for (const auto& indirectFunc : wasm.table.names) {
- std::string sig(getSig(wasm.getFunction(indirectFunc)));
- auto* funcType = ensureFunctionType(sig, &wasm, wasm.allocator);
+ wasm::Builder wasmBuilder(out.wasm);
+ for (const auto& indirectFunc : out.wasm.table.names) {
+ std::string sig(getSig(out.wasm.getFunction(indirectFunc)));
+ auto* funcType = ensureFunctionType(sig, &out.wasm, out.wasm.allocator);
if (!sigs.insert(sig).second) continue; // Sig is already in the set
std::vector<NameType> params;
params.emplace_back("fptr", i32); // function pointer param
@@ -278,7 +279,7 @@ void Linker::makeDynCallThunks() {
}
Expression* call = wasmBuilder.makeCallIndirect(funcType, fptr, std::move(args));
f->body = funcType->result == none ? call : wasmBuilder.makeReturn(call);
- wasm.addFunction(f);
+ out.wasm.addFunction(f);
exportFunction(f->name, true);
}
}
diff --git a/src/wasm-linker.h b/src/wasm-linker.h
index 9065c4b3e..023cf198c 100644
--- a/src/wasm-linker.h
+++ b/src/wasm-linker.h
@@ -29,7 +29,9 @@
namespace wasm {
-class Linker {
+// An "object file" for linking. Contains a wasm module, plus the associated
+// information needed for linking/layout.
+class LinkerObject {
public:
struct Relocation {
enum Kind { kData, kFunction };
@@ -43,50 +45,7 @@ class Linker {
kind(kind), data(data), symbol(symbol), addend(addend) {}
};
- Linker(Module& wasm, size_t globalBase, size_t stackAllocation,
- size_t userInitialMemory, size_t userMaxMemory,
- bool ignoreUnknownSymbols, Name startFunction,
- bool debug) :
- wasm(wasm),
- ignoreUnknownSymbols(ignoreUnknownSymbols),
- startFunction(startFunction),
- globalBase(globalBase),
- nextStatic(globalBase),
- userInitialMemory(userInitialMemory),
- userMaxMemory(userMaxMemory),
- stackAllocation(stackAllocation),
- debug(debug) {
- if (userMaxMemory && userMaxMemory < userInitialMemory) {
- Fatal() << "Specified max memory " << userMaxMemory <<
- " is < specified initial memory " << userInitialMemory;
- }
- if (roundUpToPageSize(userMaxMemory) != userMaxMemory) {
- Fatal() << "Specified max memory " << userMaxMemory <<
- " is not a multiple of 64k";
- }
- if (roundUpToPageSize(userInitialMemory) != userInitialMemory) {
- Fatal() << "Specified initial memory " << userInitialMemory <<
- " is not a multiple of 64k";
- }
- // Don't allow anything to be allocated at address 0
- if (globalBase == 0) nextStatic = 1;
- // Place the stack pointer at the bottom of the linear memory, to keep its
- // address small (and thus with a small encoding).
- placeStackPointer(stackAllocation);
- // Allocate __dso_handle. For asm.js, emscripten provides this in JS, but
- // wasm modules can't import data objects. Its value is 0 for the main
- // executable, which is all we have with static linking. In the future this
- // can go in a crtbegin or similar file.
- addStatic(4, 4, "__dso_handle");
- }
-
- // Allocate a static variable and return its address in linear memory
- size_t allocateStatic(size_t allocSize, size_t alignment, Name name) {
- size_t address = alignAddr(nextStatic, alignment);
- staticAddresses[name] = address;
- nextStatic = address + allocSize;
- return address;
- }
+ LinkerObject() {}
// Allocate a static object
void addStatic(size_t allocSize, size_t alignment, Name name) {
@@ -98,7 +57,7 @@ class Linker {
}
void addRelocation(Relocation::Kind kind, uint32_t* target, Name name, int addend) {
- relocations.emplace_back(make_unique<Relocation>(kind, target, name, addend));
+ relocations.emplace_back(new Relocation(kind, target, name, addend));
}
Relocation* getCurrentRelocation() {
return relocations.back().get();
@@ -132,14 +91,13 @@ class Linker {
assert(implementedFunctions.count(name));
}
- // Allocate the user stack, set up the initial memory size of the module, lay
- // out the linear memory, process the relocations, and set up the indirect
- // function table.
- void layout();
+ bool isEmpty() {
+ return wasm.functions.empty();
+ }
- // Support for emscripten integration: generates dyncall thunks, emits
- // metadata for asmConsts, staticBump and initializer functions.
- void emscriptenGlue(std::ostream& o);
+ friend class Linker;
+
+ Module wasm;
private:
struct StaticObject {
@@ -150,6 +108,87 @@ class Linker {
allocSize(allocSize), alignment(alignment), name(name) {}
};
+ std::vector<Name> globls;
+
+ std::vector<StaticObject> staticObjects;
+ std::vector<std::unique_ptr<Relocation>> relocations;
+
+ std::set<Name> implementedFunctions;
+ std::unordered_map<cashew::IString, Name> aliasedFunctions;
+
+ std::map<Name, size_t> segments; // name => segment index (in wasm module)
+
+ std::vector<Name> initializerFunctions;
+
+ LinkerObject(const LinkerObject&) = delete;
+ LinkerObject& operator=(const LinkerObject&) = delete;
+
+};
+
+// Class which performs some linker-like functionality; namely taking an object
+// file with relocations, laying out the linear memory and segments, and
+// applying the relocations, resulting in an executable wasm module.
+class Linker {
+ public:
+ Linker(size_t globalBase, size_t stackAllocation,
+ size_t userInitialMemory, size_t userMaxMemory,
+ bool ignoreUnknownSymbols, Name startFunction,
+ bool debug) :
+ ignoreUnknownSymbols(ignoreUnknownSymbols),
+ startFunction(startFunction),
+ globalBase(globalBase),
+ nextStatic(globalBase),
+ userInitialMemory(userInitialMemory),
+ userMaxMemory(userMaxMemory),
+ stackAllocation(stackAllocation),
+ debug(debug) {
+ if (userMaxMemory && userMaxMemory < userInitialMemory) {
+ Fatal() << "Specified max memory " << userMaxMemory <<
+ " is < specified initial memory " << userInitialMemory;
+ }
+ if (roundUpToPageSize(userMaxMemory) != userMaxMemory) {
+ Fatal() << "Specified max memory " << userMaxMemory <<
+ " is not a multiple of 64k";
+ }
+ if (roundUpToPageSize(userInitialMemory) != userInitialMemory) {
+ Fatal() << "Specified initial memory " << userInitialMemory <<
+ " is not a multiple of 64k";
+ }
+ // Don't allow anything to be allocated at address 0
+ if (globalBase == 0) nextStatic = 1;
+
+ // Place the stack pointer at the bottom of the linear memory, to keep its
+ // address small (and thus with a small encoding).
+ placeStackPointer(stackAllocation);
+ // Allocate __dso_handle. For asm.js, emscripten provides this in JS, but
+ // wasm modules can't import data objects. Its value is 0 for the main
+ // executable, which is all we have with static linking. In the future this
+ // can go in a crtbegin or similar file.
+ out.addStatic(4, 4, "__dso_handle");
+ }
+
+ // Return a reference to the LinkerObject for the main executable. If empty,
+ // it can be passed to an S2WasmBuilder and constructed.
+ LinkerObject& getOutput() { return out; }
+
+ // Allocate the user stack, set up the initial memory size of the module, lay
+ // out the linear memory, process the relocations, and set up the indirect
+ // function table.
+ void layout();
+
+ // Support for emscripten integration: generates dyncall thunks, emits
+ // metadata for asmConsts, staticBump and initializer functions.
+ void emscriptenGlue(std::ostream& o);
+
+ private:
+ // Allocate a static variable and return its address in linear memory
+ size_t allocateStatic(size_t allocSize, size_t alignment, Name name) {
+ size_t address = alignAddr(nextStatic, alignment);
+ staticAddresses[name] = address;
+ nextStatic = address + allocSize;
+ return address;
+ }
+
// Allocate space for a stack pointer and (if stackAllocation > 0) set up a
// relocation for it to point to the top of the stack.
void placeStackPointer(size_t stackAllocation);
@@ -175,21 +214,21 @@ class Linker {
}
void exportFunction(Name name, bool must_export) {
- if (!wasm.checkFunction(name)) {
+ if (!out.wasm.checkFunction(name)) {
assert(!must_export);
return;
}
- if (wasm.checkExport(name)) return; // Already exported
- auto exp = wasm.allocator.alloc<Export>();
+ if (out.wasm.checkExport(name)) return; // Already exported
+ auto exp = out.wasm.allocator.alloc<Export>();
exp->name = exp->value = name;
- wasm.addExport(exp);
+ out.wasm.addExport(exp);
}
+ // The output module (linked executable)
+ LinkerObject out;
- Module& wasm;
bool ignoreUnknownSymbols;
Name startFunction;
- std::vector<Name> globls;
// where globals can start to be statically allocated, i.e., the data segment
size_t globalBase;
@@ -200,21 +239,10 @@ class Linker {
size_t stackAllocation;
bool debug;
- std::vector<StaticObject> staticObjects;
std::unordered_map<cashew::IString, int32_t> staticAddresses; // name => address
-
- std::vector<std::unique_ptr<Relocation>> relocations;
-
- std::set<Name> implementedFunctions;
- std::unordered_map<cashew::IString, Name> aliasedFunctions;
-
- std::map<Name, size_t> segments; // name => segment index (in wasm module)
std::unordered_map<size_t, size_t> segmentsByAddress; // address => segment index
-
std::unordered_map<cashew::IString, size_t> functionIndexes;
- std::vector<Name> initializerFunctions;
-
};