diff options
author | Derek Schuff <dschuff@chromium.org> | 2016-04-26 11:08:43 -0700 |
---|---|---|
committer | Derek Schuff <dschuff@chromium.org> | 2016-04-26 11:08:43 -0700 |
commit | a0ec089707a33be6a4e29d917a7664519df50afc (patch) | |
tree | c86ac2d1464989cf9c43d9c61604a1f560f8481f /src/wasm-linker.cpp | |
parent | 25a81de39898b7acd4d813779f3f605784203d27 (diff) | |
download | binaryen-a0ec089707a33be6a4e29d917a7664519df50afc.tar.gz binaryen-a0ec089707a33be6a4e29d917a7664519df50afc.tar.bz2 binaryen-a0ec089707a33be6a4e29d917a7664519df50afc.zip |
Defer creation of CallImports to link time (#395)
s2wasm currently creates a Call AST node if the target is implemented in the current object (thus far assumed to be the final executable) and a CallImport node if not. In preparation for adding additional objects to the link before layout time, we make only Call nodes until link time, and then convert them to CallImport if they are undefined at that time.
Diffstat (limited to 'src/wasm-linker.cpp')
-rw-r--r-- | src/wasm-linker.cpp | 29 |
1 files changed, 28 insertions, 1 deletions
diff --git a/src/wasm-linker.cpp b/src/wasm-linker.cpp index 2e5787670..4fb7ea4ae 100644 --- a/src/wasm-linker.cpp +++ b/src/wasm-linker.cpp @@ -49,13 +49,40 @@ void Linker::placeStackPointer(size_t stackAllocation) { } void Linker::layout() { + // Convert calls to undefined functions to call_imports + for (const auto& f : out.undefinedFunctions) { + Name target = f.first; + // Create an import for the target if necessary. + if (!out.wasm.checkImport(target)) { + auto import = out.wasm.allocator.alloc<Import>(); + import->name = import->base = target; + import->module = ENV; + import->type = ensureFunctionType(getSig(*f.second.begin()), &out.wasm, + out.wasm.allocator); + out.wasm.addImport(import); + } + // Change each call. The target is the same since it's still the name. + // Delete and re-allocate the Expression as CallImport to avoid undefined + // behavior. + static_assert(sizeof(Call) >= sizeof(CallImport), + "Cannot reallocate a CallImport in a Call arena slot"); + for (auto* call : f.second) { + Call callCopy = std::move(*call); + call->~Call(); + CallImport* newCall = new (call) CallImport; + newCall->type = callCopy.type; + newCall->operands = std::move(callCopy.operands); + newCall->target = target; + } + } + // Allocate all user statics 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 : out.segments) { + for (const auto& seg : out.segments) { size_t address = staticAddresses[seg.first]; out.wasm.memory.segments[seg.second].offset = address; segmentsByAddress[address] = seg.second; |