diff options
author | Derek Schuff <dschuff@chromium.org> | 2016-02-03 11:19:03 -0800 |
---|---|---|
committer | Derek Schuff <dschuff@chromium.org> | 2016-02-04 14:56:47 -0800 |
commit | c081e08014473a66f7e1a496fdeb3477c1325d7f (patch) | |
tree | 2990a37607887d0a681c7795ad145c8e68ea2a94 /src | |
parent | 3b89982be258921b120dfb2e951533b3e87b70e1 (diff) | |
download | binaryen-c081e08014473a66f7e1a496fdeb3477c1325d7f.tar.gz binaryen-c081e08014473a66f7e1a496fdeb3477c1325d7f.tar.bz2 binaryen-c081e08014473a66f7e1a496fdeb3477c1325d7f.zip |
Add an option to allocate space for user stack at link time
Currently s2wasm pre-allocates space for the special __stack_pointer
variable but not for the actual stack, and __stack_pointer is null. On
real systems the stack is allocated by the dynamic linker, thread
runtime, or other toolchain/system-provided startup code. Since we don't
have any of that in wasm yet, just add an option to allocate the stack
in the linker for now, so we can continue to run single-file libc-free tests.
Diffstat (limited to 'src')
-rw-r--r-- | src/s2wasm-main.cpp | 11 | ||||
-rw-r--r-- | src/s2wasm.h | 34 |
2 files changed, 40 insertions, 5 deletions
diff --git a/src/s2wasm-main.cpp b/src/s2wasm-main.cpp index c3f3d0a2f..e75147b75 100644 --- a/src/s2wasm-main.cpp +++ b/src/s2wasm-main.cpp @@ -46,6 +46,11 @@ int main(int argc, const char *argv[]) { [](Options *o, const std::string &argument) { o->extra["global-base"] = argument; }) + .add("--allocate-stack", "-s", "Size of the user stack in linear memory", + Options::Arguments::One, + [](Options *o, const std::string &argument) { + o->extra["stack-allocation"] = argument; + }) .add_positional("INFILE", Options::Arguments::One, [](Options *o, const std::string &argument) { o->extra["infile"] = argument; @@ -59,9 +64,13 @@ int main(int argc, const char *argv[]) { size_t globalBase = options.extra.find("global-base") != options.extra.end() ? std::stoull(options.extra["global-base"]) : 1; + size_t stackAllocation = + options.extra.find("stack-allocation") != options.extra.end() + ? std::stoull(options.extra["stack-allocation"]) + : 0; if (options.debug) std::cerr << "Global base " << globalBase << '\n'; S2WasmBuilder s2wasm(wasm, input.c_str(), options.debug, globalBase, - ignoreUnknownSymbols); + stackAllocation, ignoreUnknownSymbols); if (options.debug) std::cerr << "Emscripten gluing..." << std::endl; std::stringstream meta; diff --git a/src/s2wasm.h b/src/s2wasm.h index 2a2a36028..1e0a28b43 100644 --- a/src/s2wasm.h +++ b/src/s2wasm.h @@ -42,7 +42,8 @@ class S2WasmBuilder { public: S2WasmBuilder(AllocatingModule& wasm, const char* input, bool debug, - size_t globalBase, bool ignoreUnknownSymbols) + size_t globalBase, size_t stackAllocation, + bool ignoreUnknownSymbols) : wasm(wasm), allocator(wasm.allocator), debug(debug), @@ -52,8 +53,13 @@ class S2WasmBuilder { s = input; scan(); s = input; - prepare(); + // Place the stack pointer at the bottom of the linear memory, to keep its + // address small (and thus with a small encoding). + placeStackPointer(stackAllocation); process(); + // Place the stack after the user's static data, to keep those addresses + // small. + if (stackAllocation) placeStack(stackAllocation); fix(); } @@ -370,10 +376,30 @@ class S2WasmBuilder { } } - void prepare() { + void placeStackPointer(size_t stackAllocation) { assert(nextStatic == globalBase); // we are the first allocation + // Allocate space for the stack pointer staticAddresses["__stack_pointer"] = nextStatic; - nextStatic += 4; + const size_t pointerSize = 4; + if (stackAllocation) { + // If we are also allocating the stack, initialize the stack pointer to + // point to one past-the-end of the stack allocation. + auto* raw = new uint32_t; + relocations.emplace_back(raw, ".stack", stackAllocation); + assert(wasm.memory.segments.size() == 0); + addressSegments[nextStatic] = wasm.memory.segments.size(); + wasm.memory.segments.emplace_back( + nextStatic, reinterpret_cast<char*>(raw), pointerSize); + wasm.memory.initial = nextStatic + pointerSize; + } + nextStatic += pointerSize; + } + + void placeStack(size_t stackAllocation) { + // Allocate space for a user stack. It starts zeroed-out so needs no segment + staticAddresses[".stack"] = nextStatic; + nextStatic += stackAllocation; + wasm.memory.initial = nextStatic; } void process() { |