summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xauto_update_tests.py2
-rwxr-xr-xcheck.py2
-rw-r--r--src/tools/wasm-ctor-eval.cpp80
-rw-r--r--src/wasm-interpreter.h4
-rw-r--r--test/ctor-eval/ignore-external-input.wast63
-rw-r--r--test/ctor-eval/ignore-external-input.wast.ctors1
-rw-r--r--test/ctor-eval/ignore-external-input.wast.out17
-rw-r--r--test/lit/help/wasm-ctor-eval.test3
8 files changed, 161 insertions, 11 deletions
diff --git a/auto_update_tests.py b/auto_update_tests.py
index 76728f8a7..9f93142a8 100755
--- a/auto_update_tests.py
+++ b/auto_update_tests.py
@@ -87,6 +87,8 @@ def update_ctor_eval_tests():
print('..', os.path.basename(t))
ctors = open(t + '.ctors').read().strip()
cmd = shared.WASM_CTOR_EVAL + [t, '-all', '-o', 'a.wast', '-S', '--ctors', ctors]
+ if 'ignore-external-input' in t:
+ cmd += ['--ignore-external-input']
support.run_command(cmd)
actual = open('a.wast').read()
out = t + '.out'
diff --git a/check.py b/check.py
index f75ef50e0..6b272f4b4 100755
--- a/check.py
+++ b/check.py
@@ -116,6 +116,8 @@ def run_ctor_eval_tests():
print('..', os.path.basename(t))
ctors = open(t + '.ctors').read().strip()
cmd = shared.WASM_CTOR_EVAL + [t, '-all', '-o', 'a.wat', '-S', '--ctors', ctors]
+ if 'ignore-external-input' in t:
+ cmd += ['--ignore-external-input']
support.run_command(cmd)
actual = open('a.wat').read()
out = t + '.out'
diff --git a/src/tools/wasm-ctor-eval.cpp b/src/tools/wasm-ctor-eval.cpp
index b0a1c0551..009a91c0b 100644
--- a/src/tools/wasm-ctor-eval.cpp
+++ b/src/tools/wasm-ctor-eval.cpp
@@ -142,7 +142,7 @@ std::unique_ptr<Module> buildEnvModule(Module& wasm) {
// create empty functions with similar signature
ModuleUtils::iterImportedFunctions(wasm, [&](Function* func) {
- if (func->module == "env") {
+ if (func->module == env->name) {
Builder builder(*env);
auto* copied = ModuleUtils::copyFunction(func, *env);
copied->module = Name();
@@ -155,7 +155,7 @@ std::unique_ptr<Module> buildEnvModule(Module& wasm) {
// create tables with similar initial and max values
ModuleUtils::iterImportedTables(wasm, [&](Table* table) {
- if (table->module == "env") {
+ if (table->module == env->name) {
auto* copied = ModuleUtils::copyTable(table, *env);
copied->module = Name();
copied->base = Name();
@@ -165,7 +165,7 @@ std::unique_ptr<Module> buildEnvModule(Module& wasm) {
});
ModuleUtils::iterImportedGlobals(wasm, [&](Global* global) {
- if (global->module == "env") {
+ if (global->module == env->name) {
auto* copied = ModuleUtils::copyGlobal(global, *env);
copied->module = Name();
copied->base = Name();
@@ -179,7 +179,7 @@ std::unique_ptr<Module> buildEnvModule(Module& wasm) {
// create an exported memory with the same initial and max size
ModuleUtils::iterImportedMemories(wasm, [&](Memory* memory) {
- if (memory->module == "env") {
+ if (memory->module == env->name) {
env->memory.name = wasm.memory.name;
env->memory.exists = true;
env->memory.initial = memory->initial;
@@ -194,6 +194,11 @@ std::unique_ptr<Module> buildEnvModule(Module& wasm) {
return env;
}
+// Whether to ignore external input to the program as it runs. If set, we will
+// assume that stdin is empty, that any env vars we try to read are not set,
+// that there are not arguments passed to main, etc.
+static bool ignoreExternalInput = false;
+
struct CtorEvalExternalInterface : EvallingModuleInstance::ExternalInterface {
Module* wasm;
EvallingModuleInstance* instance;
@@ -242,10 +247,63 @@ struct CtorEvalExternalInterface : EvallingModuleInstance::ExternalInterface {
}
Literals callImport(Function* import, LiteralList& arguments) override {
+ Name WASI("wasi_snapshot_preview1");
+
+ if (ignoreExternalInput) {
+ if (import->module == WASI) {
+ if (import->base == "environ_sizes_get") {
+ if (arguments.size() != 2 || arguments[0].type != Type::i32 ||
+ import->getResults() != Type::i32) {
+ throw FailToEvalException("wasi environ_sizes_get has wrong sig");
+ }
+
+ // Write out a count of i32(0) and return __WASI_ERRNO_SUCCESS (0).
+ store32(arguments[0].geti32(), 0);
+ return {Literal(int32_t(0))};
+ }
+
+ if (import->base == "environ_get") {
+ if (arguments.size() != 2 || arguments[0].type != Type::i32 ||
+ import->getResults() != Type::i32) {
+ throw FailToEvalException("wasi environ_get has wrong sig");
+ }
+
+ // Just return __WASI_ERRNO_SUCCESS (0).
+ return {Literal(int32_t(0))};
+ }
+
+ if (import->base == "args_sizes_get") {
+ if (arguments.size() != 2 || arguments[0].type != Type::i32 ||
+ import->getResults() != Type::i32) {
+ throw FailToEvalException("wasi args_sizes_get has wrong sig");
+ }
+
+ // Write out an argc of i32(0) and return a __WASI_ERRNO_SUCCESS (0).
+ store32(arguments[0].geti32(), 0);
+ return {Literal(int32_t(0))};
+ }
+
+ if (import->base == "args_get") {
+ if (arguments.size() != 2 || arguments[0].type != Type::i32 ||
+ import->getResults() != Type::i32) {
+ throw FailToEvalException("wasi args_get has wrong sig");
+ }
+
+ // Just return __WASI_ERRNO_SUCCESS (0).
+ return {Literal(int32_t(0))};
+ }
+
+ // Otherwise, we don't recognize this import; continue normally to
+ // error.
+ }
+ }
+
std::string extra;
if (import->module == ENV && import->base == "___cxa_atexit") {
extra = "\nrecommendation: build with -s NO_EXIT_RUNTIME=1 so that calls "
"to atexit are not emitted";
+ } else if (import->module == WASI && !ignoreExternalInput) {
+ extra = "\nrecommendation: consider --ignore-external-input";
}
throw FailToEvalException(std::string("call import: ") +
import->module.str + "." + import->base.str +
@@ -416,14 +474,14 @@ private:
};
void evalCtors(Module& wasm, std::vector<std::string> ctors) {
+ std::map<Name, std::shared_ptr<EvallingModuleInstance>> linkedInstances;
+
// build and link the env module
auto envModule = buildEnvModule(wasm);
CtorEvalExternalInterface envInterface;
auto envInstance =
std::make_shared<EvallingModuleInstance>(*envModule, &envInterface);
-
- std::map<Name, std::shared_ptr<EvallingModuleInstance>> linkedInstances;
- linkedInstances["env"] = envInstance;
+ linkedInstances[envModule->name] = envInstance;
CtorEvalExternalInterface interface(linkedInstances);
try {
@@ -525,6 +583,14 @@ int main(int argc, const char* argv[]) {
WasmCtorEvalOption,
Options::Arguments::One,
[&](Options* o, const std::string& argument) { ctorsString = argument; })
+ .add("--ignore-external-input",
+ "-ipi",
+ "Assumes no env vars are to be read, stdin is empty, etc.",
+ WasmCtorEvalOption,
+ Options::Arguments::Zero,
+ [&](Options* o, const std::string& argument) {
+ ignoreExternalInput = true;
+ })
.add_positional("INFILE",
Options::Arguments::One,
[](Options* o, const std::string& argument) {
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h
index ecfc00d93..600310c9c 100644
--- a/src/wasm-interpreter.h
+++ b/src/wasm-interpreter.h
@@ -35,10 +35,6 @@
#include "wasm-traversal.h"
#include "wasm.h"
-#ifdef WASM_INTERPRETER_DEBUG
-#include "wasm-printing.h"
-#endif
-
namespace wasm {
struct WasmException {
diff --git a/test/ctor-eval/ignore-external-input.wast b/test/ctor-eval/ignore-external-input.wast
new file mode 100644
index 000000000..0849c67ab
--- /dev/null
+++ b/test/ctor-eval/ignore-external-input.wast
@@ -0,0 +1,63 @@
+(module
+ (import "wasi_snapshot_preview1" "environ_sizes_get" (func $wasi_environ_sizes_get (param i32 i32) (result i32)))
+ (import "wasi_snapshot_preview1" "environ_get" (func $wasi_environ_get (param i32 i32) (result i32)))
+
+ (import "wasi_snapshot_preview1" "args_sizes_get" (func $wasi_args_sizes_get (param i32 i32) (result i32)))
+ (import "wasi_snapshot_preview1" "args_get" (func $wasi_args_get (param i32 i32) (result i32)))
+
+ (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
+
+ (func "test1"
+ ;; This is ok to call: when ignoring external input we assume there is no
+ ;; environment to read.
+ (i32.store
+ (i32.const 0) ;; the result (0) will be written to address 0
+ (call $wasi_environ_sizes_get
+ (i32.const 4) ;; count (0) will be written to address 4
+ (i32.const 0)
+ )
+ )
+ (i32.store
+ (i32.const 8) ;; the result (0) will be written to address 8
+ (call $wasi_environ_get
+ (i32.const 0)
+ (i32.const 0)
+ )
+ )
+ )
+
+ (func "test2"
+ ;; This is also ok to call: when ignoring external input we assume there are
+ ;; not args passed to main.
+ (i32.store
+ (i32.const 12) ;; the result (0) will be written to address 12
+ (call $wasi_args_sizes_get
+ (i32.const 16) ;; argc (0) will be written to address 16
+ (i32.const 0)
+ )
+ )
+ (i32.store
+ (i32.const 20) ;; the result (0) will be written to address 20
+ (call $wasi_args_get
+ (i32.const 0)
+ (i32.const 0)
+ )
+ )
+ )
+
+ (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
+ ;; output.
+ (drop
+ (call $wasi_something_else)
+ )
+ (i32.store
+ (i32.const 24)
+ (i32.const 100)
+ )
+ )
+)
diff --git a/test/ctor-eval/ignore-external-input.wast.ctors b/test/ctor-eval/ignore-external-input.wast.ctors
new file mode 100644
index 000000000..c7060ede5
--- /dev/null
+++ b/test/ctor-eval/ignore-external-input.wast.ctors
@@ -0,0 +1 @@
+test1,test2,test3
diff --git a/test/ctor-eval/ignore-external-input.wast.out b/test/ctor-eval/ignore-external-input.wast.out
new file mode 100644
index 000000000..f728afd0e
--- /dev/null
+++ b/test/ctor-eval/ignore-external-input.wast.out
@@ -0,0 +1,17 @@
+(module
+ (type $none_=>_i32 (func (result i32)))
+ (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
+ (drop
+ (call $wasi_something_else)
+ )
+ (i32.store
+ (i32.const 24)
+ (i32.const 100)
+ )
+ )
+)
diff --git a/test/lit/help/wasm-ctor-eval.test b/test/lit/help/wasm-ctor-eval.test
index cf0671c81..364ac5d4c 100644
--- a/test/lit/help/wasm-ctor-eval.test
+++ b/test/lit/help/wasm-ctor-eval.test
@@ -19,6 +19,9 @@
;; CHECK-NEXT: --ctors,-c Comma-separated list of global
;; CHECK-NEXT: constructor functions to evaluate
;; CHECK-NEXT:
+;; CHECK-NEXT: --ignore-external-input,-ipi Assumes no env vars are to be read, stdin
+;; CHECK-NEXT: is empty, etc.
+;; CHECK-NEXT:
;; CHECK-NEXT:
;; CHECK-NEXT: Tool options:
;; CHECK-NEXT: -------------