summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/StackCheck.cpp61
-rw-r--r--test/passes/stack-check_enable-mutable-globals.txt22
-rw-r--r--test/passes/stack-check_enable-mutable-globals.wast10
3 files changed, 62 insertions, 31 deletions
diff --git a/src/passes/StackCheck.cpp b/src/passes/StackCheck.cpp
index c25d70635..23fd5be3d 100644
--- a/src/passes/StackCheck.cpp
+++ b/src/passes/StackCheck.cpp
@@ -22,6 +22,7 @@
#include "abi/js.h"
#include "ir/import-utils.h"
+#include "ir/names.h"
#include "pass.h"
#include "shared-constants.h"
#include "support/debug.h"
@@ -31,11 +32,6 @@
namespace wasm {
-// The base is where the stack begins. As it goes down, that is the highest
-// valid address.
-static Name STACK_BASE("__stack_base");
-// The limit is the farthest it can grow to, which is the lowest valid address.
-static Name STACK_LIMIT("__stack_limit");
// Exported function to set the base and the limit.
static Name SET_STACK_LIMITS("__set_stack_limits");
@@ -60,18 +56,6 @@ static void addExportedFunction(Module& module,
module.addExport(std::move(export_));
}
-static void generateSetStackLimitFunctions(Module& module) {
- Builder builder(module);
- auto limitsFunc = builder.makeFunction(
- SET_STACK_LIMITS, Signature({Type::i32, Type::i32}, Type::none), {});
- LocalGet* getBase = builder.makeLocalGet(0, Type::i32);
- Expression* storeBase = builder.makeGlobalSet(STACK_BASE, getBase);
- LocalGet* getLimit = builder.makeLocalGet(1, Type::i32);
- Expression* storeLimit = builder.makeGlobalSet(STACK_LIMIT, getLimit);
- limitsFunc->body = builder.makeBlock({storeBase, storeLimit});
- addExportedFunction(module, std::move(limitsFunc));
-}
-
struct EnforceStackLimits : public WalkerPass<PostWalker<EnforceStackLimits>> {
EnforceStackLimits(const Global* stackPointer,
const Global* stackBase,
@@ -142,6 +126,10 @@ struct StackCheck : public Pass {
return;
}
+ // Pick appropriate names.
+ auto stackBaseName = Names::getValidGlobalName(*module, "__stack_base");
+ auto stackLimitName = Names::getValidGlobalName(*module, "__stack_limit");
+
Name handler;
auto handlerName =
runner->options.getArgumentOrDefault("stack-check-handler", "");
@@ -151,22 +139,33 @@ struct StackCheck : public Pass {
}
Builder builder(*module);
- auto stackBase = builder.makeGlobal(STACK_BASE,
- stackPointer->type,
- builder.makeConst(int32_t(0)),
- Builder::Mutable);
-
- auto stackLimit = builder.makeGlobal(STACK_LIMIT,
- stackPointer->type,
- builder.makeConst(int32_t(0)),
- Builder::Mutable);
+
+ // Add the globals.
+ auto stackBase =
+ module->addGlobal(builder.makeGlobal(stackBaseName,
+ stackPointer->type,
+ builder.makeConst(int32_t(0)),
+ Builder::Mutable));
+ auto stackLimit =
+ module->addGlobal(builder.makeGlobal(stackLimitName,
+ stackPointer->type,
+ builder.makeConst(int32_t(0)),
+ Builder::Mutable));
+
+ // Instrument all the code.
PassRunner innerRunner(module);
- EnforceStackLimits(
- stackPointer, stackBase.get(), stackLimit.get(), builder, handler)
+ EnforceStackLimits(stackPointer, stackBase, stackLimit, builder, handler)
.run(&innerRunner, module);
- module->addGlobal(std::move(stackBase));
- module->addGlobal(std::move(stackLimit));
- generateSetStackLimitFunctions(*module);
+
+ // Generate the exported function.
+ auto limitsFunc = builder.makeFunction(
+ SET_STACK_LIMITS, Signature({Type::i32, Type::i32}, Type::none), {});
+ auto* getBase = builder.makeLocalGet(0, Type::i32);
+ auto* storeBase = builder.makeGlobalSet(stackBaseName, getBase);
+ auto* getLimit = builder.makeLocalGet(1, Type::i32);
+ auto* storeLimit = builder.makeGlobalSet(stackLimitName, getLimit);
+ limitsFunc->body = builder.makeBlock({storeBase, storeLimit});
+ addExportedFunction(*module, std::move(limitsFunc));
}
};
diff --git a/test/passes/stack-check_enable-mutable-globals.txt b/test/passes/stack-check_enable-mutable-globals.txt
index c89f112a8..3f8aa4da7 100644
--- a/test/passes/stack-check_enable-mutable-globals.txt
+++ b/test/passes/stack-check_enable-mutable-globals.txt
@@ -39,3 +39,25 @@
)
)
)
+(module
+ (type $i32_i32_=>_none (func (param i32 i32)))
+ (type $none_=>_i32 (func (result i32)))
+ (import "env" "__stack_pointer" (global $sp (mut i32)))
+ (global $__stack_base (mut i32) (i32.const 0))
+ (global $__stack_limit (mut i32) (i32.const 0))
+ (global $__stack_base_0 (mut i32) (i32.const 0))
+ (global $__stack_limit_0 (mut i32) (i32.const 0))
+ (export "use_stack" (func $0))
+ (export "__set_stack_limits" (func $__set_stack_limits))
+ (func $0 (result i32)
+ (unreachable)
+ )
+ (func $__set_stack_limits (param $0 i32) (param $1 i32)
+ (global.set $__stack_base_0
+ (local.get $0)
+ )
+ (global.set $__stack_limit_0
+ (local.get $1)
+ )
+ )
+)
diff --git a/test/passes/stack-check_enable-mutable-globals.wast b/test/passes/stack-check_enable-mutable-globals.wast
index 3028039fd..c3583cd2c 100644
--- a/test/passes/stack-check_enable-mutable-globals.wast
+++ b/test/passes/stack-check_enable-mutable-globals.wast
@@ -5,3 +5,13 @@
(global.get $sp)
)
)
+;; if the global names are taken we should not crash
+(module
+ (import "env" "__stack_pointer" (global $sp (mut i32)))
+ (global $__stack_base (mut i32) (i32.const 0))
+ (global $__stack_limit (mut i32) (i32.const 0))
+ (export "use_stack" (func $0))
+ (func $0 (result i32)
+ (unreachable)
+ )
+)