summaryrefslogtreecommitdiff
path: root/src/tools/js-wrapper.h
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2019-01-10 19:31:20 -0800
committerGitHub <noreply@github.com>2019-01-10 19:31:20 -0800
commit45714b5fc6cf14c112bc4f188aca427464ab69d8 (patch)
tree11a85c5fce2dfaa36650e0e6766d4d3f8b0a2366 /src/tools/js-wrapper.h
parent4084d6e70922f8b1cc00c3a24bf5db41e03d5e79 (diff)
downloadbinaryen-45714b5fc6cf14c112bc4f188aca427464ab69d8.tar.gz
binaryen-45714b5fc6cf14c112bc4f188aca427464ab69d8.tar.bz2
binaryen-45714b5fc6cf14c112bc4f188aca427464ab69d8.zip
Compare binaryen fuzz-exec to JS VMs (#1856)
The main fuzz_opt.py script compares JS VMs, and separately runs binaryen's fuzz-exec that compares the binaryen interpreter to itself (before and after opts). This PR lets us directly compare binaryen's interpreter output to JS VMs. This found a bunch of minor things we can do better on both sides, giving more fuzz coverage. To enable this, a bunch of tiny fixes were needed: * Add --fuzz-exec-before which is like --fuzz-exec but just runs the code before opts are run, instead of before and after. * Normalize double printing (so JS and C++ print comparable things). This includes negative zero in JS, which we never printed properly til now. * Various improvements to how we print fuzz-exec logging - remove unuseful things, and normalize the others across JS and C++. * Properly legalize the wasm when --emit-js-wrapper (i.e., we will run the code from JS), and use that in the JS wrapper code.
Diffstat (limited to 'src/tools/js-wrapper.h')
-rw-r--r--src/tools/js-wrapper.h48
1 files changed, 28 insertions, 20 deletions
diff --git a/src/tools/js-wrapper.h b/src/tools/js-wrapper.h
index 7cf2ffc53..765a638c5 100644
--- a/src/tools/js-wrapper.h
+++ b/src/tools/js-wrapper.h
@@ -22,10 +22,6 @@
namespace wasm {
static std::string generateJSWrapper(Module& wasm) {
- PassRunner runner(&wasm);
- runner.add("legalize-js-interface");
- runner.run();
-
std::string ret;
ret += "if (typeof console === 'undefined') {\n"
" console = { log: print };\n"
@@ -49,12 +45,26 @@ static std::string generateJSWrapper(Module& wasm) {
" binary = read(args[0], 'binary');\n"
" }\n"
"}\n"
+ "function literal(x, type) {\n"
+ " var ret = type + '.const ';\n"
+ " switch (type) {\n"
+ " case 'i32': ret += (x | 0); break;\n"
+ " case 'f32':\n"
+ " case 'f64': {\n"
+ " if (x == 0 && (1 / x) < 0) ret += '-';\n"
+ " ret += x;\n"
+ " break;\n"
+ " }\n"
+ " default: throw 'what?';\n"
+ " }\n"
+ " return ret;\n"
+ "}\n"
"var instance = new WebAssembly.Instance(new WebAssembly.Module(binary), {\n"
" 'fuzzing-support': {\n"
- " 'log-i32': function(x) { console.log('i32: ' + x) },\n"
- " 'log-i64': function(x, y) { console.log('i64: ' + x + ', ' + y) },\n"
- " 'log-f32': function(x) { console.log('f32: ' + x) },\n"
- " 'log-f64': function(x) { console.log('f64: ' + x) }\n"
+ " 'log-i32': function(x) { console.log('[LoggingExternalInterface logging ' + literal(x, 'i32') + ']') },\n"
+ " 'log-i64': function(x, y) { console.log('[LoggingExternalInterface logging ' + literal(x, 'i32') + ' ' + literal(y, 'i32') + ']') },\n" // legalization: two i32s
+ " 'log-f32': function(x) { console.log('[LoggingExternalInterface logging ' + literal(x, 'f64') + ']') },\n" // legalization: an f64
+ " 'log-f64': function(x) { console.log('[LoggingExternalInterface logging ' + literal(x, 'f64') + ']') },\n"
" },\n"
" 'env': {\n"
" 'setTempRet0': function(x) { tempRet0 = x },\n"
@@ -64,22 +74,17 @@ static std::string generateJSWrapper(Module& wasm) {
for (auto& exp : wasm.exports) {
auto* func = wasm.getFunctionOrNull(exp->value);
if (!func) continue; // something exported other than a function
- auto bad = false; // check for things we can't support
- for (Type param : func->params) {
- if (param == i64) bad = true;
- }
- if (func->result == i64) bad = true;
- if (bad) continue;
ret += "if (instance.exports.hangLimitInitializer) instance.exports.hangLimitInitializer();\n";
ret += "try {\n";
- ret += std::string(" console.log('calling: ") + exp->name.str + "');\n";
+ ret += std::string(" console.log('[fuzz-exec] calling $") + exp->name.str + "');\n";
if (func->result != none) {
- ret += " console.log(' result: ' + ";
+ ret += std::string(" console.log('[fuzz-exec] note result: $") + exp->name.str + " => ' + literal(";
+ } else {
+ ret += " ";
}
ret += std::string("instance.exports.") + exp->name.str + "(";
bool first = true;
for (Type param : func->params) {
- WASM_UNUSED(param);
// zeros in arguments TODO more?
if (first) {
first = false;
@@ -87,17 +92,20 @@ static std::string generateJSWrapper(Module& wasm) {
ret += ", ";
}
ret += "0";
+ if (param == i64) {
+ ret += ", 0";
+ }
}
ret += ")";
if (func->result != none) {
- ret += ")"; // for console.log
+ ret += ", '" + std::string(printType(func->result)) + "'))";
+ // TODO: getTempRet
}
ret += ";\n";
ret += "} catch (e) {\n";
- ret += " console.log(' exception: ' + e);\n";
+ ret += " console.log('exception: ' + e);\n";
ret += "}\n";
}
- ret += "console.log('done.')\n";
return ret;
}