@@ -55,8 +55,11 @@ struct LoggingExternalInterface : public ShellExternalInterface {
55
55
ModuleRunner* instance = nullptr ;
56
56
57
57
public:
58
- LoggingExternalInterface (Loggings& loggings, Module& wasm)
59
- : loggings(loggings), wasm(wasm) {
58
+ LoggingExternalInterface (
59
+ Loggings& loggings,
60
+ Module& wasm,
61
+ std::map<Name, std::shared_ptr<ModuleRunner>> linkedInstances_ = {})
62
+ : ShellExternalInterface(linkedInstances_), loggings(loggings), wasm(wasm) {
60
63
for (auto & exp : wasm.exports ) {
61
64
if (exp->kind == ExternalKind::Table && exp->name == " table" ) {
62
65
exportedTable = *exp->getInternalName ();
@@ -185,7 +188,11 @@ struct LoggingExternalInterface : public ShellExternalInterface {
185
188
} else if (import ->base == " getTempRet0" ) {
186
189
return {Literal (state.tempRet0 )};
187
190
}
191
+ } else if (linkedInstances.count (import ->module )) {
192
+ // This is from a recognized module.
193
+ return getImportInstance (import )->callExport (import ->base , arguments);
188
194
}
195
+ // Anything else, we ignore.
189
196
std::cerr << " [LoggingExternalInterface ignoring an unknown import "
190
197
<< import ->module << " . " << import ->base << ' \n ' ;
191
198
return {};
@@ -279,35 +286,24 @@ struct ExecutionResults {
279
286
// If set, we should ignore this and not compare it to anything.
280
287
bool ignore = false ;
281
288
282
- // get results of execution
283
- void get (Module& wasm) {
284
- LoggingExternalInterface interface (loggings, wasm);
289
+ // Get results of executing a module. Optionally, provide a second module to
290
+ // link with it (like fuzz_shell's second module).
291
+ void get (Module& wasm, Module* second = nullptr ) {
285
292
try {
286
- ModuleRunner instance (wasm, &interface);
287
- // This is not an optimization: we want to execute anything, even relaxed
288
- // SIMD instructions.
289
- instance.setRelaxedBehavior (ModuleRunner::RelaxedBehavior::Execute);
290
- instance.instantiate ();
291
- interface.setModuleRunner (&instance);
292
- // execute all exported methods (that are therefore preserved through
293
- // opts)
294
- for (auto & exp : wasm.exports ) {
295
- if (exp->kind != ExternalKind::Function) {
296
- continue ;
297
- }
298
- std::cout << " [fuzz-exec] calling " << exp->name << " \n " ;
299
- auto * func = wasm.getFunction (*exp->getInternalName ());
300
- FunctionResult ret = run (func, wasm, instance);
301
- results[exp->name ] = ret;
302
- if (auto * values = std::get_if<Literals>(&ret)) {
303
- // ignore the result if we hit an unreachable and returned no value
304
- if (values->size () > 0 ) {
305
- std::cout << " [fuzz-exec] note result: " << exp->name << " => " ;
306
- for (auto value : *values) {
307
- printValue (value);
308
- }
309
- }
310
- }
293
+ // Run the first module.
294
+ LoggingExternalInterface interface (loggings, wasm);
295
+ auto instance = std::make_shared<ModuleRunner>(wasm, &interface);
296
+ runModule (wasm, *instance, interface);
297
+
298
+ if (second) {
299
+ // Link and run the second module.
300
+ std::map<Name, std::shared_ptr<ModuleRunner>> linkedInstances;
301
+ linkedInstances[" primary" ] = instance;
302
+ LoggingExternalInterface secondInterface (
303
+ loggings, *second, linkedInstances);
304
+ auto secondInstance = std::make_shared<ModuleRunner>(
305
+ *second, &secondInterface, linkedInstances);
306
+ runModule (*second, *secondInstance, secondInterface);
311
307
}
312
308
} catch (const TrapException&) {
313
309
// May throw in instance creation (init of offsets).
@@ -319,6 +315,36 @@ struct ExecutionResults {
319
315
}
320
316
}
321
317
318
+ void runModule (Module& wasm,
319
+ ModuleRunner& instance,
320
+ LoggingExternalInterface& interface) {
321
+ // This is not an optimization: we want to execute anything, even relaxed
322
+ // SIMD instructions.
323
+ instance.setRelaxedBehavior (ModuleRunner::RelaxedBehavior::Execute);
324
+ instance.instantiate ();
325
+ interface.setModuleRunner (&instance);
326
+ // execute all exported methods (that are therefore preserved through
327
+ // opts)
328
+ for (auto & exp : wasm.exports ) {
329
+ if (exp->kind != ExternalKind::Function) {
330
+ continue ;
331
+ }
332
+ std::cout << " [fuzz-exec] calling " << exp->name << " \n " ;
333
+ auto * func = wasm.getFunction (*exp->getInternalName ());
334
+ FunctionResult ret = run (func, wasm, instance);
335
+ results[exp->name ] = ret;
336
+ if (auto * values = std::get_if<Literals>(&ret)) {
337
+ // ignore the result if we hit an unreachable and returned no value
338
+ if (values->size () > 0 ) {
339
+ std::cout << " [fuzz-exec] note result: " << exp->name << " => " ;
340
+ for (auto value : *values) {
341
+ printValue (value);
342
+ }
343
+ }
344
+ }
345
+ }
346
+ }
347
+
322
348
void printValue (Literal value) {
323
349
// Unwrap an externalized GC value to get the actual value, but not strings,
324
350
// which are normally a subtype of ext.
0 commit comments