summaryrefslogtreecommitdiff
path: root/src/tools/wasm-ctor-eval.cpp
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2022-01-12 13:17:50 -0800
committerGitHub <noreply@github.com>2022-01-12 21:17:50 +0000
commit29604f1a7e9ef9dcc2825f076849cd6a452a8a19 (patch)
treec4d8b432f10c675122463342ecd89280468ff8c5 /src/tools/wasm-ctor-eval.cpp
parent10b1ad720d5f5c991cd7049f8650011d89869f60 (diff)
downloadbinaryen-29604f1a7e9ef9dcc2825f076849cd6a452a8a19.tar.gz
binaryen-29604f1a7e9ef9dcc2825f076849cd6a452a8a19.tar.bz2
binaryen-29604f1a7e9ef9dcc2825f076849cd6a452a8a19.zip
[ctor-eval] Eval functions with params if ignoring external input (#4446)
When ignoring external input, assume params have a value of 0. This makes it possible to eval main(argc, argv) if one is careful and does not actually use those values. This is basically a workaround for main always receiving argc/argv, even if the C code has no args (in that case the compiler emits __original_main for the user's main, and wraps it with a main that adds the args, hence the problem). This is similar to the existing support for handling wasi_args_get when ignoring external input, although it just sets values of zeros for the params. Perhaps it could check for main() specifically and return 1 for argc and a proper buffer for argv somehow, but I think if a program wants to use --ignore-external-input it can avoid actually reading argc/argv.
Diffstat (limited to 'src/tools/wasm-ctor-eval.cpp')
-rw-r--r--src/tools/wasm-ctor-eval.cpp30
1 files changed, 24 insertions, 6 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();