]> git.proxmox.com Git - rustc.git/blob - src/binaryen/src/tools/execution-results.h
New upstream version 1.23.0+dfsg1
[rustc.git] / src / binaryen / src / tools / execution-results.h
1 /*
2 * Copyright 2017 WebAssembly Community Group participants
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 //
18 // Shared execution result checking code
19 //
20
21 #include "wasm.h"
22 #include "shell-interface.h"
23
24 namespace wasm {
25
26 // gets execution results from a wasm module. this is useful for fuzzing
27 //
28 // we can only get results when there are no imports. we then call each method
29 // that has a result, with some values
30 struct ExecutionResults {
31 std::map<Name, Literal> results;
32
33 // get results of execution
34 void get(Module& wasm) {
35 if (wasm.imports.size() > 0) {
36 std::cout << "[fuzz-exec] imports, so quitting\n";
37 return;
38 }
39 ShellExternalInterface interface;
40 ModuleInstance instance(wasm, &interface);
41 // execute all exported methods (that are therefore preserved through opts)
42 for (auto& exp : wasm.exports) {
43 if (exp->kind != ExternalKind::Function) continue;
44 auto* func = wasm.getFunction(exp->value);
45 if (func->result != none) {
46 // this has a result
47 results[exp->name] = run(func, wasm, instance);
48 std::cout << "[fuzz-exec] note result: " << exp->name << " => " << results[exp->name] << '\n';
49 } else {
50 // no result, run it anyhow (it might modify memory etc.)
51 run(func, wasm, instance);
52 std::cout << "[fuzz-exec] no result for void func: " << exp->name << '\n';
53 }
54 }
55 std::cout << "[fuzz-exec] " << results.size() << " results noted\n";
56 }
57
58 // get current results and check them against previous ones
59 void check(Module& wasm) {
60 ExecutionResults optimizedResults;
61 optimizedResults.get(wasm);
62 if (optimizedResults != *this) {
63 std::cout << "[fuzz-exec] optimization passes changed execution results";
64 abort();
65 }
66 std::cout << "[fuzz-exec] " << results.size() << " results match\n";
67 }
68
69 bool operator==(ExecutionResults& other) {
70 for (auto& iter : results) {
71 auto name = iter.first;
72 if (other.results.find(name) == other.results.end()) {
73 std::cout << "[fuzz-exec] missing " << name << '\n';
74 abort();
75 }
76 std::cout << "[fuzz-exec] comparing " << name << '\n';
77 if (!results[name].bitwiseEqual(other.results[name])) {
78 std::cout << "not identical!\n";
79 abort();
80 }
81 }
82 return true;
83 }
84
85 bool operator!=(ExecutionResults& other) {
86 return !((*this) == other);
87 }
88
89 Literal run(Function* func, Module& wasm) {
90 ShellExternalInterface interface;
91 try {
92 ModuleInstance instance(wasm, &interface);
93 return run(func, wasm, instance);
94 } catch (const TrapException&) {
95 // may throw in instance creation (init of offsets)
96 return Literal();
97 }
98 }
99
100 Literal run(Function* func, Module& wasm, ModuleInstance& instance) {
101 try {
102 LiteralList arguments;
103 // init hang support, if present
104 if (wasm.getFunctionOrNull("hangLimitInitializer")) {
105 instance.callFunction("hangLimitInitializer", arguments);
106 }
107 // call the method
108 for (WasmType param : func->params) {
109 // zeros in arguments TODO: more?
110 arguments.push_back(Literal(param));
111 }
112 return instance.callFunction(func->name, arguments);
113 } catch (const TrapException&) {
114 return Literal();
115 }
116 }
117 };
118
119 } // namespace wasm
120