Skip to content

Commit 632351d

Browse files
authored
Add stack-pointer argument to post-emscripten pass. (#2823)
This allows emscripten to statically set the initial value of the stack pointer. Should allow use to avoid doing it dynamically at startup: emscripten-core/emscripten#11031
1 parent 107e2fd commit 632351d

File tree

5 files changed

+37
-7
lines changed

5 files changed

+37
-7
lines changed

src/passes/PostEmscripten.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,11 @@
2828
#include <pass.h>
2929
#include <shared-constants.h>
3030
#include <wasm-builder.h>
31+
#include <wasm-emscripten.h>
3132
#include <wasm.h>
3233

34+
#define DEBUG_TYPE "post-emscripten"
35+
3336
namespace wasm {
3437

3538
namespace {
@@ -75,6 +78,24 @@ struct OptimizeCalls : public WalkerPass<PostWalker<OptimizeCalls>> {
7578

7679
struct PostEmscripten : public Pass {
7780
void run(PassRunner* runner, Module* module) override {
81+
// Apply the stack pointer, if it was provided. This is needed here
82+
// because the emscripten JS compiler can add static data allocations that
83+
// come before the stack.
84+
auto stackPtrStr =
85+
runner->options.getArgumentOrDefault("stack-pointer", "");
86+
if (stackPtrStr != "") {
87+
Global* stackPointer = getStackPointerGlobal(*module);
88+
BYN_TRACE("stack_pointer: " << stackPtrStr << "\n");
89+
if (stackPointer && !stackPointer->imported()) {
90+
auto stackPtr = std::stoi(stackPtrStr);
91+
auto oldValue = stackPointer->init->cast<Const>()->value;
92+
BYN_TRACE("updating __stack_pointer: " << oldValue.geti32() << " -> "
93+
<< stackPtr << "\n");
94+
stackPointer->init =
95+
Builder(*module).makeConst(Literal(int32_t(stackPtr)));
96+
}
97+
}
98+
7899
// Apply the sbrk ptr, if it was provided.
79100
auto sbrkPtrStr =
80101
runner->options.getArgumentOrDefault("emscripten-sbrk-ptr", "");

src/wasm-emscripten.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323

2424
namespace wasm {
2525

26+
Global* getStackPointerGlobal(Module& wasm);
27+
2628
// Class which modifies a wasm module for use with emscripten. Generates
2729
// runtime functions and emits metadata.
2830
class EmscriptenGlueGenerator {
@@ -78,7 +80,6 @@ class EmscriptenGlueGenerator {
7880
// so far.
7981
std::unordered_set<Signature> sigs;
8082

81-
Global* getStackPointerGlobal();
8283
Expression* generateLoadStackPointer();
8384
Expression* generateStoreStackPointer(Function* func, Expression* value);
8485
void generateDynCallThunk(Signature sig);

src/wasm/wasm-emscripten.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ bool isExported(Module& wasm, Name name) {
6565
return false;
6666
}
6767

68-
Global* EmscriptenGlueGenerator::getStackPointerGlobal() {
68+
Global* getStackPointerGlobal(Module& wasm) {
6969
// Assumption: The stack pointer is either imported as __stack_pointer or
7070
// its the first non-imported and non-exported global.
7171
// TODO(sbc): Find a better way to discover the stack pointer. Perhaps the
@@ -92,7 +92,7 @@ Expression* EmscriptenGlueGenerator::generateLoadStackPointer() {
9292
/* ptr =*/builder.makeConst(Literal(0)),
9393
/* type =*/Type::i32);
9494
}
95-
Global* stackPointer = getStackPointerGlobal();
95+
Global* stackPointer = getStackPointerGlobal(wasm);
9696
if (!stackPointer) {
9797
Fatal() << "stack pointer global not found";
9898
}
@@ -142,7 +142,7 @@ EmscriptenGlueGenerator::generateStoreStackPointer(Function* func,
142142
/* value =*/value,
143143
/* type =*/Type::i32);
144144
}
145-
Global* stackPointer = getStackPointerGlobal();
145+
Global* stackPointer = getStackPointerGlobal(wasm);
146146
if (!stackPointer) {
147147
Fatal() << "stack pointer global not found";
148148
}
@@ -530,7 +530,7 @@ struct RemoveStackPointer : public PostWalker<RemoveStackPointer> {
530530
// __stack_pointer and initializes it from an immutable global instead.
531531
// For -shared builds we instead call replaceStackPointerGlobal.
532532
void EmscriptenGlueGenerator::internalizeStackPointerGlobal() {
533-
Global* stackPointer = getStackPointerGlobal();
533+
Global* stackPointer = getStackPointerGlobal(wasm);
534534
if (!stackPointer || !stackPointer->imported() || !stackPointer->mutable_) {
535535
return;
536536
}
@@ -552,7 +552,7 @@ void EmscriptenGlueGenerator::internalizeStackPointerGlobal() {
552552
}
553553

554554
void EmscriptenGlueGenerator::replaceStackPointerGlobal() {
555-
Global* stackPointer = getStackPointerGlobal();
555+
Global* stackPointer = getStackPointerGlobal(wasm);
556556
if (!stackPointer) {
557557
return;
558558
}
@@ -606,7 +606,7 @@ struct StackLimitEnforcer : public WalkerPass<PostWalker<StackLimitEnforcer>> {
606606
};
607607

608608
void EmscriptenGlueGenerator::enforceStackLimit() {
609-
Global* stackPointer = getStackPointerGlobal();
609+
Global* stackPointer = getStackPointerGlobal(wasm);
610610
if (!stackPointer) {
611611
return;
612612
}

test/passes/[email protected]

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
(module
2+
(import "env" "not_stack" (global $import$global0 i32))
3+
(global $should_be_stack_pointer (mut i32) (i32.const 1234))
4+
)

test/passes/[email protected]

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
(module
2+
(import "env" "not_stack" (global i32))
3+
(global $should_be_stack_pointer (mut i32) (i32.const 2))
4+
)

0 commit comments

Comments
 (0)