2 * Copyright 2017 WebAssembly Community Group participants
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 // Shared execution result checking code
22 #include "shell-interface.h"
26 // gets execution results from a wasm module. this is useful for fuzzing
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
;
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";
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
) {
47 results
[exp
->name
] = run(func
, wasm
, instance
);
48 std::cout
<< "[fuzz-exec] note result: " << exp
->name
<< " => " << results
[exp
->name
] << '\n';
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';
55 std::cout
<< "[fuzz-exec] " << results
.size() << " results noted\n";
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";
66 std::cout
<< "[fuzz-exec] " << results
.size() << " results match\n";
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';
76 std::cout
<< "[fuzz-exec] comparing " << name
<< '\n';
77 if (!results
[name
].bitwiseEqual(other
.results
[name
])) {
78 std::cout
<< "not identical!\n";
85 bool operator!=(ExecutionResults
& other
) {
86 return !((*this) == other
);
89 Literal
run(Function
* func
, Module
& wasm
) {
90 ShellExternalInterface interface
;
92 ModuleInstance
instance(wasm
, &interface
);
93 return run(func
, wasm
, instance
);
94 } catch (const TrapException
&) {
95 // may throw in instance creation (init of offsets)
100 Literal
run(Function
* func
, Module
& wasm
, ModuleInstance
& instance
) {
102 LiteralList arguments
;
103 // init hang support, if present
104 if (wasm
.getFunctionOrNull("hangLimitInitializer")) {
105 instance
.callFunction("hangLimitInitializer", arguments
);
108 for (WasmType param
: func
->params
) {
109 // zeros in arguments TODO: more?
110 arguments
.push_back(Literal(param
));
112 return instance
.callFunction(func
->name
, arguments
);
113 } catch (const TrapException
&) {