WIP: support stack pointer, setlocal
diff --git a/src/s2wasm.h b/src/s2wasm.h
index d14de82..4e9b009 100644
--- a/src/s2wasm.h
+++ b/src/s2wasm.h
@@ -46,6 +46,7 @@
   std::unique_ptr<LinkerObject::SymbolInfo> symbolInfo;
   std::unordered_map<uint32_t, uint32_t> fileIndexMap;
   std::vector<Global*> globalVars;
+  int stackPointerGlobalIndex;
 
  public:
   S2WasmBuilder(const char* input, bool debug)
@@ -54,7 +55,8 @@
         debug(debug),
         wasm(nullptr),
         allocator(nullptr),
-        linkerObj(nullptr)
+        linkerObj(nullptr),
+        stackPointerGlobalIndex(-1)
         {}
 
   void build(LinkerObject *obj) {
@@ -65,8 +67,16 @@
     wasm = &obj->wasm;
     allocator = &wasm->allocator;
     for (auto global : globalVars) {
+      auto c = allocator->alloc<Const>();
+      c->type = i32;
+      c->value = Literal(0);
+      global->init = c;
       wasm->addGlobal(global);
     }
+    if (stackPointerGlobalIndex != -1) {
+      auto g = globalVars[stackPointerGlobalIndex];
+      obj->stackPointerGlobalName = g->name;
+    }
 
     s = inputStart;
     process();
@@ -474,6 +484,9 @@
         global->type = type;
         global->mutable_ = true;
         globalVars.push_back(global);
+      } else if (match(".stack_pointer")) {
+        assert(stackPointerGlobalIndex == -1);
+        stackPointerGlobalIndex = getInt();
       } else {
         // add data aliases
         Name lhs = getStrToSep();
@@ -1272,9 +1285,16 @@
         Name assign = getAssign();
         skipComma();
         auto curr = allocator->alloc<GetLocal>();
-        curr->index = getInt();
-        curr->type = i32;
+        int index = getInt();
+        curr->index = index;
+        curr->type = func->getLocalType(index);
         setOutput(curr, assign);
+      } else if (match("set_local")) {
+        auto curr = allocator->alloc<SetLocal>();
+        curr->index = getInt();
+        skipComma();
+        curr->value = getInput();
+        addToBlock(curr);
       } else if (match("get_global")) {
         Name assign = getAssign();
         skipComma();
diff --git a/src/tools/s2wasm.cpp b/src/tools/s2wasm.cpp
index a357834..1797a8b 100644
--- a/src/tools/s2wasm.cpp
+++ b/src/tools/s2wasm.cpp
@@ -155,6 +155,7 @@
   if (generateEmscriptenGlue) {
     emscripten::generateRuntimeFunctions(linker.getOutput());
   }
+  emscripten::generateStackRestoreFunction(linker.getOutput());
 
   linker.layout();
 
diff --git a/src/wasm-emscripten.cpp b/src/wasm-emscripten.cpp
index 43366e4..91df5e7 100644
--- a/src/wasm-emscripten.cpp
+++ b/src/wasm-emscripten.cpp
@@ -65,32 +65,40 @@
   ));
 }
 
-Load* generateLoadStackPointer(Builder& builder, LinkerObject& linker) {
-  Load* load = builder.makeLoad(
-    /* bytes  =*/ 4,
-    /* signed =*/ false,
-    /* offset =*/ 0,
-    /* align  =*/ 4,
-    /* ptr    =*/ builder.makeConst(Literal(0)),
-    /* type   =*/ i32
-  );
-  addStackPointerRelocation(linker, &load->offset.addr);
-  return load;
+Expression* generateLoadStackPointer(Builder& builder, LinkerObject& linker) {
+  if (linker.stackPointerGlobalName.str) {
+    return builder.makeGetGlobal(linker.stackPointerGlobalName, i32);
+  } else {
+    Load* load = builder.makeLoad(
+      /* bytes  =*/ 4,
+      /* signed =*/ false,
+      /* offset =*/ 0,
+      /* align  =*/ 4,
+      /* ptr    =*/ builder.makeConst(Literal(0)),
+      /* type   =*/ i32
+    );
+    addStackPointerRelocation(linker, &load->offset.addr);
+    return load;
+  }
 }
 
-Store* generateStoreStackPointer(Builder& builder,
-                                 LinkerObject& linker,
-                                 Expression* value) {
-  Store* store = builder.makeStore(
-    /* bytes  =*/ 4,
-    /* offset =*/ 0,
-    /* align  =*/ 4,
-    /* ptr    =*/ builder.makeConst(Literal(0)),
-    /* value  =*/ value,
-    /* type   =*/ i32
-  );
-  addStackPointerRelocation(linker, &store->offset.addr);
-  return store;
+Expression* generateStoreStackPointer(Builder& builder,
+                                      LinkerObject& linker,
+                                      Expression* value) {
+  if (linker.stackPointerGlobalName.str) {
+    return builder.makeSetGlobal(linker.stackPointerGlobalName, value);
+  } else {
+    Store* store = builder.makeStore(
+      /* bytes  =*/ 4,
+      /* offset =*/ 0,
+      /* align  =*/ 4,
+      /* ptr    =*/ builder.makeConst(Literal(0)),
+      /* value  =*/ value,
+      /* type   =*/ i32
+    );
+    addStackPointerRelocation(linker, &store->offset.addr);
+    return store;
+  }
 }
 
 void generateStackSaveFunction(LinkerObject& linker) {
@@ -115,7 +123,7 @@
   Function* function = builder.makeFunction(
     name, std::move(params), i32, { { "1", i32 } }
   );
-  Load* loadStack = generateLoadStackPointer(builder, linker);
+  Expression* loadStack = generateLoadStackPointer(builder, linker);
   SetLocal* setStackLocal = builder.makeSetLocal(1, loadStack);
   GetLocal* getStackLocal = builder.makeGetLocal(1, i32);
   GetLocal* getSizeArg = builder.makeGetLocal(0, i32);
@@ -128,7 +136,7 @@
     builder.makeBinary(AddInt32, add, addConst),
     builder.makeConst(Literal(~bitMask))
   );
-  Store* storeStack = generateStoreStackPointer(builder, linker, maskedAdd);
+  Expression* storeStack = generateStoreStackPointer(builder, linker, maskedAdd);
 
   Block* block = builder.makeBlock();
   block->list.push_back(setStackLocal);
@@ -149,7 +157,7 @@
     name, std::move(params), none, {}
   );
   GetLocal* getArg = builder.makeGetLocal(0, i32);
-  Store* store = generateStoreStackPointer(builder, linker, getArg);
+  Expression* store = generateStoreStackPointer(builder, linker, getArg);
 
   function->body = store;
 
@@ -159,7 +167,6 @@
 void generateRuntimeFunctions(LinkerObject& linker) {
   generateStackSaveFunction(linker);
   generateStackAllocFunction(linker);
-  generateStackRestoreFunction(linker);
 }
 
 static bool hasI64ResultOrParam(FunctionType* ft) {
diff --git a/src/wasm-emscripten.h b/src/wasm-emscripten.h
index 7400a8b..b7f4159 100644
--- a/src/wasm-emscripten.h
+++ b/src/wasm-emscripten.h
@@ -27,6 +27,7 @@
 
 void generateRuntimeFunctions(LinkerObject& linker);
 void generateMemoryGrowthFunction(Module&);
+void generateStackRestoreFunction(LinkerObject& linker);
 
 // Create thunks for use with emscripten Runtime.dynCall. Creates one for each
 // signature in the indirect function table.
diff --git a/src/wasm-linker.h b/src/wasm-linker.h
index 2129f4f..d74f308 100644
--- a/src/wasm-linker.h
+++ b/src/wasm-linker.h
@@ -159,6 +159,7 @@
   friend class Linker;
 
   Module wasm;
+  Name stackPointerGlobalName;
 
  private:
   struct StaticObject {