@@ -78,124 +78,131 @@ struct LoggingExternalInterface : public ShellExternalInterface {
78
78
}
79
79
}
80
80
81
- Flow callImport (Function* import , const Literals& arguments) override {
82
- if (import ->module == " fuzzing-support" ) {
83
- if (import ->base .startsWith (" log" )) {
84
- // This is a logging function like log-i32 or log-f64
85
- std::cout << " [LoggingExternalInterface " ;
86
- if (import ->base == " log-branch" ) {
87
- // Report this as a special logging, so we can differentiate it from
88
- // the others in the fuzzer.
89
- std::cout << " log-branch" ;
90
- } else {
91
- // All others are just reported as loggings.
92
- std::cout << " logging" ;
93
- }
94
- loggings.push_back (Literal ()); // buffer with a None between calls
95
- for (auto argument : arguments) {
96
- if (argument.type == Type::i64 ) {
97
- // To avoid JS legalization changing logging results, treat a
98
- // logging of an i64 as two i32s (which is what legalization would
99
- // turn us into).
100
- auto low = Literal (int32_t (argument.getInteger ()));
101
- auto high = Literal (int32_t (argument.getInteger () >> int32_t (32 )));
102
- std::cout << ' ' << low;
103
- loggings.push_back (low);
104
- std::cout << ' ' << high;
105
- loggings.push_back (high);
81
+ Literal getImportedFunction (Function* import ) override {
82
+ if (linkedInstances.count (import ->module )) {
83
+ return getImportInstance (import )->getExportedFunction (import ->base );
84
+ }
85
+ auto f = [import , this ](const Literals& arguments) -> Flow {
86
+ if (import ->module == " fuzzing-support" ) {
87
+ if (import ->base .startsWith (" log" )) {
88
+ // This is a logging function like log-i32 or log-f64
89
+ std::cout << " [LoggingExternalInterface " ;
90
+ if (import ->base == " log-branch" ) {
91
+ // Report this as a special logging, so we can differentiate it
92
+ // from the others in the fuzzer.
93
+ std::cout << " log-branch" ;
106
94
} else {
107
- std::cout << ' ' << argument;
108
- loggings. push_back (argument) ;
95
+ // All others are just reported as loggings.
96
+ std::cout << " logging " ;
109
97
}
110
- }
111
- std::cout << " ]\n " ;
112
- return {};
113
- } else if (import ->base == " throw" ) {
114
- // Throw something, depending on the value of the argument. 0 means we
115
- // should throw a JS exception, and any other value means we should
116
- // throw a wasm exception (with that value as the payload).
117
- if (arguments[0 ].geti32 () == 0 ) {
118
- throwJSException ();
119
- } else {
120
- auto payload = std::make_shared<ExnData>(wasmTag, arguments);
121
- throwException (WasmException{Literal (payload)});
122
- }
123
- } else if (import ->base == " table-get" ) {
124
- // Check for errors here, duplicating tableLoad(), because that will
125
- // trap, and we just want to throw an exception (the same as JS would).
126
- if (!exportedTable) {
127
- throwJSException ();
128
- }
129
- auto index = arguments[0 ].getUnsigned ();
130
- if (index >= tables[exportedTable].size ()) {
131
- throwJSException ();
132
- }
133
- return {tableLoad (exportedTable, index)};
134
- } else if (import ->base == " table-set" ) {
135
- if (!exportedTable) {
136
- throwJSException ();
137
- }
138
- auto index = arguments[0 ].getUnsigned ();
139
- if (index >= tables[exportedTable].size ()) {
140
- throwJSException ();
141
- }
142
- tableStore (exportedTable, index, arguments[1 ]);
143
- return {};
144
- } else if (import ->base == " call-export" ) {
145
- callExportAsJS (arguments[0 ].geti32 ());
146
- // The second argument determines if we should catch and rethrow
147
- // exceptions. There is no observable difference in those two modes in
148
- // the binaryen interpreter, so we don't need to do anything.
149
-
150
- // Return nothing. If we wanted to return a value we'd need to have
151
- // multiple such functions, one for each signature.
152
- return {};
153
- } else if (import ->base == " call-export-catch" ) {
154
- try {
98
+ loggings.push_back (Literal ()); // buffer with a None between calls
99
+ for (auto argument : arguments) {
100
+ if (argument.type == Type::i64 ) {
101
+ // To avoid JS legalization changing logging results, treat a
102
+ // logging of an i64 as two i32s (which is what legalization
103
+ // would turn us into).
104
+ auto low = Literal (int32_t (argument.getInteger ()));
105
+ auto high =
106
+ Literal (int32_t (argument.getInteger () >> int32_t (32 )));
107
+ std::cout << ' ' << low;
108
+ loggings.push_back (low);
109
+ std::cout << ' ' << high;
110
+ loggings.push_back (high);
111
+ } else {
112
+ std::cout << ' ' << argument;
113
+ loggings.push_back (argument);
114
+ }
115
+ }
116
+ std::cout << " ]\n " ;
117
+ return {};
118
+ } else if (import ->base == " throw" ) {
119
+ // Throw something, depending on the value of the argument. 0 means
120
+ // we should throw a JS exception, and any other value means we
121
+ // should throw a wasm exception (with that value as the payload).
122
+ if (arguments[0 ].geti32 () == 0 ) {
123
+ throwJSException ();
124
+ } else {
125
+ auto payload = std::make_shared<ExnData>(wasmTag, arguments);
126
+ throwException (WasmException{Literal (payload)});
127
+ }
128
+ } else if (import ->base == " table-get" ) {
129
+ // Check for errors here, duplicating tableLoad(), because that will
130
+ // trap, and we just want to throw an exception (the same as JS
131
+ // would).
132
+ if (!exportedTable) {
133
+ throwJSException ();
134
+ }
135
+ auto index = arguments[0 ].getUnsigned ();
136
+ if (index >= tables[exportedTable].size ()) {
137
+ throwJSException ();
138
+ }
139
+ return {tableLoad (exportedTable, index)};
140
+ } else if (import ->base == " table-set" ) {
141
+ if (!exportedTable) {
142
+ throwJSException ();
143
+ }
144
+ auto index = arguments[0 ].getUnsigned ();
145
+ if (index >= tables[exportedTable].size ()) {
146
+ throwJSException ();
147
+ }
148
+ tableStore (exportedTable, index, arguments[1 ]);
149
+ return {};
150
+ } else if (import ->base == " call-export" ) {
155
151
callExportAsJS (arguments[0 ].geti32 ());
156
- return {Literal (int32_t (0 ))};
157
- } catch (const WasmException& e) {
158
- return {Literal (int32_t (1 ))};
159
- }
160
- } else if (import ->base == " call-ref" ) {
161
- // Similar to call-export*, but with a ref.
162
- callRefAsJS (arguments[0 ]);
163
- return {};
164
- } else if (import ->base == " call-ref-catch" ) {
165
- try {
152
+ // The second argument determines if we should catch and rethrow
153
+ // exceptions. There is no observable difference in those two modes
154
+ // in the binaryen interpreter, so we don't need to do anything.
155
+
156
+ // Return nothing. If we wanted to return a value we'd need to have
157
+ // multiple such functions, one for each signature.
158
+ return {};
159
+ } else if (import ->base == " call-export-catch" ) {
160
+ try {
161
+ callExportAsJS (arguments[0 ].geti32 ());
162
+ return {Literal (int32_t (0 ))};
163
+ } catch (const WasmException& e) {
164
+ return {Literal (int32_t (1 ))};
165
+ }
166
+ } else if (import ->base == " call-ref" ) {
167
+ // Similar to call-export*, but with a ref.
166
168
callRefAsJS (arguments[0 ]);
167
- return {Literal (int32_t (0 ))};
168
- } catch (const WasmException& e) {
169
- return {Literal (int32_t (1 ))};
169
+ return {};
170
+ } else if (import ->base == " call-ref-catch" ) {
171
+ try {
172
+ callRefAsJS (arguments[0 ]);
173
+ return {Literal (int32_t (0 ))};
174
+ } catch (const WasmException& e) {
175
+ return {Literal (int32_t (1 ))};
176
+ }
177
+ } else if (import ->base == " sleep" ) {
178
+ // Do not actually sleep, just return the id.
179
+ return {arguments[1 ]};
180
+ } else {
181
+ WASM_UNREACHABLE (" unknown fuzzer import" );
170
182
}
171
- } else if (import ->base == " sleep" ) {
172
- // Do not actually sleep, just return the id.
173
- return {arguments[1 ]};
174
- } else {
175
- WASM_UNREACHABLE (" unknown fuzzer import" );
176
- }
177
- } else if (import ->module == ENV) {
178
- if (import ->base == " log_execution" ) {
179
- std::cout << " [LoggingExternalInterface log-execution" ;
180
- for (auto argument : arguments) {
181
- std::cout << ' ' << argument;
183
+ } else if (import ->module == ENV) {
184
+ if (import ->base == " log_execution" ) {
185
+ std::cout << " [LoggingExternalInterface log-execution" ;
186
+ for (auto argument : arguments) {
187
+ std::cout << ' ' << argument;
188
+ }
189
+ std::cout << " ]\n " ;
190
+ return {};
191
+ } else if (import ->base == " setTempRet0" ) {
192
+ state.tempRet0 = arguments[0 ].geti32 ();
193
+ return {};
194
+ } else if (import ->base == " getTempRet0" ) {
195
+ return {Literal (state.tempRet0 )};
182
196
}
183
- std::cout << " ]\n " ;
184
- return {};
185
- } else if (import ->base == " setTempRet0" ) {
186
- state.tempRet0 = arguments[0 ].geti32 ();
187
- return {};
188
- } else if (import ->base == " getTempRet0" ) {
189
- return {Literal (state.tempRet0 )};
190
197
}
191
- } else if (linkedInstances. count ( import -> module )) {
192
- // This is from a recognized module.
193
- return getImportInstance ( import )-> callExport ( import ->base , arguments) ;
194
- }
195
- // Anything else, we ignore.
196
- std::cerr << " [LoggingExternalInterface ignoring an unknown import "
197
- << import -> module << " . " << import ->base << ' \n ' ;
198
- return {} ;
198
+ // Anything else, we ignore.
199
+ std::cerr << " [LoggingExternalInterface ignoring an unknown import "
200
+ << import -> module << " . " << import ->base << ' \n ' ;
201
+ return {};
202
+ };
203
+ // Use a null instance because this is a host function.
204
+ return Literal (std::make_shared<FuncData>( import ->name , nullptr , f),
205
+ import -> type ) ;
199
206
}
200
207
201
208
void throwJSException () {
0 commit comments