@@ -55,8 +55,11 @@ struct LoggingExternalInterface : public ShellExternalInterface {
5555 ModuleRunner* instance = nullptr ;
5656
5757public:
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) {
6063 for (auto & exp : wasm.exports ) {
6164 if (exp->kind == ExternalKind::Table && exp->name == " table" ) {
6265 exportedTable = *exp->getInternalName ();
@@ -185,7 +188,11 @@ struct LoggingExternalInterface : public ShellExternalInterface {
185188 } else if (import ->base == " getTempRet0" ) {
186189 return {Literal (state.tempRet0 )};
187190 }
191+ } else if (linkedInstances.count (import ->module )) {
192+ // This is from a recognized module.
193+ return getImportInstance (import )->callExport (import ->base , arguments);
188194 }
195+ // Anything else, we ignore.
189196 std::cerr << " [LoggingExternalInterface ignoring an unknown import "
190197 << import ->module << " . " << import ->base << ' \n ' ;
191198 return {};
@@ -279,35 +286,24 @@ struct ExecutionResults {
279286 // If set, we should ignore this and not compare it to anything.
280287 bool ignore = false ;
281288
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 ) {
285292 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);
311307 }
312308 } catch (const TrapException&) {
313309 // May throw in instance creation (init of offsets).
@@ -319,6 +315,36 @@ struct ExecutionResults {
319315 }
320316 }
321317
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+
322348 void printValue (Literal value) {
323349 // Unwrap an externalized GC value to get the actual value, but not strings,
324350 // which are normally a subtype of ext.
0 commit comments