diff options
author | Alon Zakai <azakai@google.com> | 2022-01-12 13:17:50 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-01-12 21:17:50 +0000 |
commit | 29604f1a7e9ef9dcc2825f076849cd6a452a8a19 (patch) | |
tree | c4d8b432f10c675122463342ecd89280468ff8c5 /src/tools/wasm-ctor-eval.cpp | |
parent | 10b1ad720d5f5c991cd7049f8650011d89869f60 (diff) | |
download | binaryen-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.cpp | 30 |
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(); |