summaryrefslogtreecommitdiff
path: root/src/wasm-linker.cpp
diff options
context:
space:
mode:
authorDerek Schuff <dschuff@chromium.org>2016-04-22 13:35:22 -0700
committerDerek Schuff <dschuff@chromium.org>2016-04-22 13:35:22 -0700
commitc12647ea31f3bb312e721ca8ca6a53246733106d (patch)
tree9280efe8aed28e6bd42e05818c2b1140d5eeb3b7 /src/wasm-linker.cpp
parent41b62f9e8c525f899177a7d34cf24312e65b1337 (diff)
downloadbinaryen-c12647ea31f3bb312e721ca8ca6a53246733106d.tar.gz
binaryen-c12647ea31f3bb312e721ca8ca6a53246733106d.tar.bz2
binaryen-c12647ea31f3bb312e721ca8ca6a53246733106d.zip
Simplify statics, segments, and relocations (#380)
Also defer address assignment until layout time in preparation for separating linker objects out from Linker
Diffstat (limited to 'src/wasm-linker.cpp')
-rw-r--r--src/wasm-linker.cpp47
1 files changed, 27 insertions, 20 deletions
diff --git a/src/wasm-linker.cpp b/src/wasm-linker.cpp
index 90ef4c2b9..2c5e0003d 100644
--- a/src/wasm-linker.cpp
+++ b/src/wasm-linker.cpp
@@ -37,21 +37,29 @@ 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.
- size_t address = allocateStatic(pointerSize, pointerSize, "__stack_pointer");
+ 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;
- relocations.emplace_back(
- make_unique<Relocation>(raw, ".stack", stackAllocation));
+ addRelocation(Relocation::kData, raw, ".stack", stackAllocation);
assert(wasm.memory.segments.size() == 0);
- addressSegments[address] = wasm.memory.segments.size();
- wasm.memory.segments.emplace_back(
- address, reinterpret_cast<char*>(raw), pointerSize);
+ addSegment("__stack_pointer", reinterpret_cast<char*>(raw), pointerSize);
}
}
void Linker::layout() {
+ // Allocate all user statics
+ for (const auto& obj : staticObjects) {
+ allocateStatic(obj.allocSize, obj.alignment, obj.name);
+ }
+ // Update the segments with their addresses now that they have been allocated.
+ for (auto& seg : segments) {
+ size_t address = staticAddresses[seg.first];
+ wasm.memory.segments[seg.second].offset = address;
+ segmentsByAddress[address] = seg.second;
+ }
+
// Place the stack after the user's static data, to keep those addresses
// small.
if (stackAllocation) allocateStatic(stackAllocation, 16, ".stack");
@@ -88,36 +96,35 @@ void Linker::layout() {
}
};
for (auto& relocation : relocations) {
- Name name = relocation->value;
+ Name name = relocation->symbol;
if (debug) std::cerr << "fix relocation " << name << '\n';
- const auto& symbolAddress = staticAddresses.find(name);
- if (symbolAddress != staticAddresses.end()) {
- *(relocation->data) = symbolAddress->second + relocation->offset;
+
+ if (relocation->kind == 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 {
- // must be a function address
- auto aliased = aliasedFunctions.find(name);
- if (aliased != aliasedFunctions.end()) name = aliased->second;
+ // function address
+ name = resolveAlias(name);
if (!wasm.checkFunction(name)) {
std::cerr << "Unknown symbol: " << name << '\n';
- if (!ignoreUnknownSymbols) abort();
+ if (!ignoreUnknownSymbols) Fatal() << "undefined reference\n";
*(relocation->data) = 0;
} else {
ensureFunctionIndex(name);
- *(relocation->data) = functionIndexes[name] + relocation->offset;
+ *(relocation->data) = functionIndexes[name] + relocation->addend;
}
}
}
if (!!startFunction) {
if (implementedFunctions.count(startFunction) == 0) {
- std::cerr << "Unknown start function: `" << startFunction << "`\n";
- abort();
+ Fatal() << "Unknown start function: `" << startFunction << "`\n";
}
const auto *target = wasm.getFunction(startFunction);
Name start("_start");
if (implementedFunctions.count(start) != 0) {
- std::cerr << "Start function already present: `" << start << "`\n";
- abort();
+ Fatal() << "Start function already present: `" << start << "`\n";
}
auto* func = wasm.allocator.alloc<Function>();
func->name = start;
@@ -173,7 +180,7 @@ void Linker::emscriptenGlue(std::ostream& o) {
void visitCallImport(CallImport* curr) {
if (curr->target == EMSCRIPTEN_ASM_CONST) {
auto arg = curr->operands[0]->cast<Const>();
- size_t segmentIndex = parent->addressSegments[arg->value.geti32()];
+ size_t segmentIndex = parent->segmentsByAddress[arg->value.geti32()];
std::string code = escape(parent->wasm.memory.segments[segmentIndex].data);
int32_t id;
if (ids.count(code) == 0) {