summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/tools/wasm-ctor-eval.cpp30
-rw-r--r--test/ctor-eval/ignore-external-input-gc.wast33
-rw-r--r--test/ctor-eval/ignore-external-input-gc.wast.ctors1
-rw-r--r--test/ctor-eval/ignore-external-input-gc.wast.out19
-rw-r--r--test/ctor-eval/ignore-external-input.wast13
-rw-r--r--test/ctor-eval/ignore-external-input.wast.ctors2
-rw-r--r--test/ctor-eval/ignore-external-input.wast.out8
-rw-r--r--test/ctor-eval/params.wast4
8 files changed, 95 insertions, 15 deletions
diff --git a/src/tools/wasm-ctor-eval.cpp b/src/tools/wasm-ctor-eval.cpp
index 871d4eac0..f49a54833 100644
--- a/src/tools/wasm-ctor-eval.cpp
+++ b/src/tools/wasm-ctor-eval.cpp
@@ -510,13 +510,30 @@ EvalCtorOutcome evalCtor(EvallingModuleInstance& instance,
auto& wasm = instance.wasm;
auto* func = wasm.getFunction(funcName);
- // We don't know the values of parameters, so give up if there are any.
- // TODO: Maybe use ignoreExternalInput?
- if (func->getNumParams() > 0) {
+ // We don't know the values of parameters, so give up if there are any, unless
+ // we are ignoring them.
+ if (func->getNumParams() > 0 && !ignoreExternalInput) {
std::cout << " ...stopping due to params\n";
+ std::cout << RECOMMENDATION "consider --ignore-external-input";
return EvalCtorOutcome();
}
+ // If there are params, we are ignoring them (or we would have quit earlier);
+ // set those up with zeros.
+ // TODO: Have a safer option here, either
+ // 1. Statically or dynamically stop evalling when a param is actually
+ // used, or
+ // 2. Split out --ignore-external-input into separate flags.
+ LiteralList params;
+ for (Index i = 0; i < func->getNumParams(); i++) {
+ auto type = func->getLocalType(i);
+ if (!LiteralUtils::canMakeZero(type)) {
+ std::cout << " ...stopping due to non-zeroable param\n";
+ return EvalCtorOutcome();
+ }
+ params.push_back(Literal::makeZero(type));
+ }
+
// We want to handle the form of the global constructor function in LLVM. That
// looks like this:
//
@@ -540,7 +557,7 @@ EvalCtorOutcome evalCtor(EvallingModuleInstance& instance,
if (auto* block = func->body->dynCast<Block>()) {
// Go through the items in the block and try to execute them. We do all this
// in a single function scope for all the executions.
- EvallingModuleInstance::FunctionScope scope(func, LiteralList());
+ EvallingModuleInstance::FunctionScope scope(func, params);
EvallingModuleInstance::RuntimeExpressionRunner expressionRunner(
instance, scope, instance.maxDepth);
@@ -549,7 +566,7 @@ EvalCtorOutcome evalCtor(EvallingModuleInstance& instance,
// the same idea as applyToModule() - we must only do it after an entire
// atomic "chunk" has been processed, we do not want partial updates from
// an item in the block that we only partially evalled.
- EvallingModuleInstance::FunctionScope appliedScope(func, LiteralList());
+ EvallingModuleInstance::FunctionScope appliedScope(func, params);
Literals results;
Index successes = 0;
@@ -647,9 +664,10 @@ EvalCtorOutcome evalCtor(EvallingModuleInstance& instance,
// Otherwise, we don't recognize a pattern that allows us to do partial
// evalling. So simply call the entire function at once and see if we can
// optimize that.
+
Literals results;
try {
- results = instance.callFunction(funcName, LiteralList());
+ results = instance.callFunction(funcName, params);
} catch (FailToEvalException& fail) {
std::cout << " ...stopping since could not eval: " << fail.why << "\n";
return EvalCtorOutcome();
diff --git a/test/ctor-eval/ignore-external-input-gc.wast b/test/ctor-eval/ignore-external-input-gc.wast
new file mode 100644
index 000000000..16558336c
--- /dev/null
+++ b/test/ctor-eval/ignore-external-input-gc.wast
@@ -0,0 +1,33 @@
+(module
+ (global $global1 (mut i32) (i32.const 10))
+ (global $global2 (mut i32) (i32.const 20))
+
+ (func "test1" (param $any (ref null any))
+ ;; This is ok to call: when ignoring external input we assume 0 for the
+ ;; parameters, and this parameter is nullable.
+ (drop
+ (local.get $any)
+ )
+ (global.set $global1
+ (i32.const 11)
+ )
+ )
+
+ (func "test2" (param $any (ref any))
+ ;; This is *not* ok to call: when ignoring external input we assume 0 for
+ ;; the parameters, and this parameter is not nullable.
+ (drop
+ (local.get $any)
+ )
+ (global.set $global2
+ (i32.const 22)
+ )
+ )
+
+ (func "keepalive" (result i32)
+ (i32.add
+ (global.get $global1)
+ (global.get $global2)
+ )
+ )
+)
diff --git a/test/ctor-eval/ignore-external-input-gc.wast.ctors b/test/ctor-eval/ignore-external-input-gc.wast.ctors
new file mode 100644
index 000000000..e4b83fcba
--- /dev/null
+++ b/test/ctor-eval/ignore-external-input-gc.wast.ctors
@@ -0,0 +1 @@
+test1,test2
diff --git a/test/ctor-eval/ignore-external-input-gc.wast.out b/test/ctor-eval/ignore-external-input-gc.wast.out
new file mode 100644
index 000000000..3e7a8f429
--- /dev/null
+++ b/test/ctor-eval/ignore-external-input-gc.wast.out
@@ -0,0 +1,19 @@
+(module
+ (type $ref|any|_=>_none (func (param (ref any))))
+ (type $none_=>_i32 (func (result i32)))
+ (global $global1 (mut i32) (i32.const 11))
+ (global $global2 (mut i32) (i32.const 20))
+ (export "test2" (func $1))
+ (export "keepalive" (func $2))
+ (func $1 (param $any (ref any))
+ (global.set $global2
+ (i32.const 22)
+ )
+ )
+ (func $2 (result i32)
+ (i32.add
+ (global.get $global1)
+ (global.get $global2)
+ )
+ )
+)
diff --git a/test/ctor-eval/ignore-external-input.wast b/test/ctor-eval/ignore-external-input.wast
index 0849c67ab..562011605 100644
--- a/test/ctor-eval/ignore-external-input.wast
+++ b/test/ctor-eval/ignore-external-input.wast
@@ -8,7 +8,7 @@
(import "wasi_snapshot_preview1" "something_else" (func $wasi_something_else (result i32)))
(memory 256 256)
- (data (i32.const 0) "aaaaaaaaaaaaaaaaaaaaaaaaaaaa") ;; the final 4 'a's will remain
+ (data (i32.const 0) "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") ;; the final 4 'a's will remain
(func "test1"
;; This is ok to call: when ignoring external input we assume there is no
@@ -48,6 +48,15 @@
)
)
+ (func "test2b" (param $x i32)
+ ;; This is also ok to call: when ignoring external input we assume the
+ ;; args are zeros.
+ (i32.store
+ (i32.const 24) ;; the result (0) will be written to address 24
+ (local.get $x)
+ )
+ )
+
(func "test3"
;; This is *not* ok to call, and we will *not* reach the final store after
;; this call. This function will not be evalled and will remain in the
@@ -56,7 +65,7 @@
(call $wasi_something_else)
)
(i32.store
- (i32.const 24)
+ (i32.const 28)
(i32.const 100)
)
)
diff --git a/test/ctor-eval/ignore-external-input.wast.ctors b/test/ctor-eval/ignore-external-input.wast.ctors
index c7060ede5..7b57e4b82 100644
--- a/test/ctor-eval/ignore-external-input.wast.ctors
+++ b/test/ctor-eval/ignore-external-input.wast.ctors
@@ -1 +1 @@
-test1,test2,test3
+test1,test2,test2b,test3
diff --git a/test/ctor-eval/ignore-external-input.wast.out b/test/ctor-eval/ignore-external-input.wast.out
index f728afd0e..d61f2e6b9 100644
--- a/test/ctor-eval/ignore-external-input.wast.out
+++ b/test/ctor-eval/ignore-external-input.wast.out
@@ -3,14 +3,14 @@
(type $none_=>_none (func))
(import "wasi_snapshot_preview1" "something_else" (func $wasi_something_else (result i32)))
(memory $0 256 256)
- (data (i32.const 24) "aaaa")
- (export "test3" (func $2))
- (func $2
+ (data (i32.const 28) "aaaa")
+ (export "test3" (func $3))
+ (func $3
(drop
(call $wasi_something_else)
)
(i32.store
- (i32.const 24)
+ (i32.const 28)
(i32.const 100)
)
)
diff --git a/test/ctor-eval/params.wast b/test/ctor-eval/params.wast
index fb70debe5..cb346bb3b 100644
--- a/test/ctor-eval/params.wast
+++ b/test/ctor-eval/params.wast
@@ -1,7 +1,7 @@
(module
(func "test1" (param $x i32)
- ;; The presence of params stops us from evalling this function (at least
- ;; for now).
+ ;; The presence of params stops us from evalling this function, at least
+ ;; not with --ignore-external-input (see ignore-external-input.wast)
(nop)
)
)