2929#define wasm_wasm_interpreter_h
3030
3131#include < cmath>
32+ #include < iomanip>
3233#include < limits.h>
3334#include < sstream>
3435#include < variant>
4647#include " wasm-limits.h"
4748#include " wasm-traversal.h"
4849#include " wasm.h"
50+ #include " wasm/import-resolver.h"
4951
5052#if __has_feature(leak_sanitizer) || __has_feature(address_sanitizer)
5153#include < sanitizer/lsan_interface.h>
@@ -2940,8 +2942,6 @@ class ConstantExpressionRunner : public ExpressionRunner<SubType> {
29402942 }
29412943};
29422944
2943- using GlobalValueSet = std::map<Name, Literals>;
2944-
29452945//
29462946// A runner for a module. Each runner contains the information to execute the
29472947// module, such as the state of globals, and so forth, so it basically
@@ -2969,7 +2969,6 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
29692969 std::map<Name, std::shared_ptr<SubType>> linkedInstances = {}) {}
29702970 virtual ~ExternalInterface () = default ;
29712971 virtual void init (Module& wasm, SubType& instance) {}
2972- virtual void importGlobals (GlobalValueSet& globals, Module& wasm) = 0;
29732972 virtual Literal getImportedFunction (Function* import ) = 0;
29742973 virtual bool growMemory (Name name, Address oldSize, Address newSize) = 0;
29752974 virtual bool growTable (Name name,
@@ -3174,18 +3173,21 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
31743173 // TODO: this duplicates module in ExpressionRunner, and can be removed
31753174 Module& wasm;
31763175
3177- // Values of globals
3178- GlobalValueSet globals;
3179-
31803176 // Multivalue ABI support (see push/pop).
31813177 std::vector<Literals> multiValues;
31823178
3179+ // keyed by internal name
3180+ std::map<Name, Literals> definedGlobals;
3181+ std::map<Name, Literals*> allGlobals;
3182+
31833183 ModuleRunnerBase (
31843184 Module& wasm,
31853185 ExternalInterface* externalInterface,
3186+ std::shared_ptr<ImportResolver> importResolver,
31863187 std::map<Name, std::shared_ptr<SubType>> linkedInstances_ = {})
31873188 : ExpressionRunner<SubType>(&wasm), wasm(wasm),
3188- externalInterface (externalInterface), linkedInstances(linkedInstances_) {
3189+ externalInterface (externalInterface), linkedInstances(linkedInstances_),
3190+ importResolver (importResolver) {
31893191 // Set up a single shared CurrContinuations for all these linked instances,
31903192 // reusing one if it exists.
31913193 std::shared_ptr<ContinuationStore> shared;
@@ -3208,16 +3210,11 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
32083210 // (This is separate from the constructor so that it does not occur
32093211 // synchronously, which makes some code patterns harder to write.)
32103212 void instantiate () {
3211- // import globals from the outside
3212- externalInterface->importGlobals (globals, wasm);
3213- // generate internal (non-imported) globals
3214- ModuleUtils::iterDefinedGlobals (wasm, [&](Global* global) {
3215- globals[global->name ] = self ()->visit (global->init ).values ;
3216- });
3217-
32183213 // initialize the rest of the external interface
32193214 externalInterface->init (wasm, *self ());
32203215
3216+ initializeGlobals ();
3217+
32213218 initializeTableContents ();
32223219 initializeMemoryContents ();
32233220
@@ -3254,20 +3251,30 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
32543251 func->type );
32553252 }
32563253
3257- // get an exported global
3258- Literals getExportedGlobal (Name name) {
3254+ std::optional<Literals*> getExportedGlobal (Name name) {
32593255 Export* export_ = wasm.getExportOrNull (name);
32603256 if (!export_ || export_->kind != ExternalKind::Global) {
3261- externalInterface-> trap ( " getExport external not found " ) ;
3257+ return std:: nullopt ;
32623258 }
32633259 Name internalName = *export_->getInternalName ();
3264- auto iter = globals .find (internalName);
3265- if (iter == globals .end ()) {
3266- externalInterface-> trap ( " getExport internal not found " ) ;
3260+ auto iter = allGlobals .find (internalName);
3261+ if (iter == allGlobals .end ()) {
3262+ return std:: nullopt ;
32673263 }
32683264 return iter->second ;
32693265 }
32703266
3267+ Literals& getExportedGlobalOrTrap (Name name) {
3268+ auto global = getExportedGlobal (name);
3269+ if (!global.has_value ()) {
3270+ externalInterface->trap ((std::stringstream ()
3271+ << " getExportedGlobal: export " << name
3272+ << " not found." )
3273+ .str ());
3274+ }
3275+ return **global;
3276+ }
3277+
32713278 Tag* getExportedTag (Name name) {
32723279 Export* export_ = wasm.getExportOrNull (name);
32733280 if (!export_ || export_->kind != ExternalKind::Tag) {
@@ -3321,6 +3328,34 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
33213328 return TableInstanceInfo{self (), name};
33223329 }
33233330
3331+ void initializeGlobals () {
3332+ for (auto & global : wasm.globals ) {
3333+ if (global->imported ()) {
3334+ QualifiedName name{global->module , global->base };
3335+ auto importedGlobal = importResolver->getGlobal (name, global->type );
3336+ if (!importedGlobal) {
3337+ externalInterface->trap (
3338+ (std::stringstream () << " Imported global " << name << " not found." )
3339+ .str ());
3340+ }
3341+ allGlobals[global->name ] = *importedGlobal;
3342+ } else {
3343+ Literals init = self ()->visit (global->init ).values ;
3344+ auto [it, inserted] = definedGlobals.emplace (global->name , init);
3345+
3346+ // This was likely checked during parsing or validation
3347+ if (!inserted) {
3348+ externalInterface->trap (
3349+ (std::stringstream ()
3350+ << " Global: " << std::quoted (global->name .toString ())
3351+ << " was defined twice." )
3352+ .str ());
3353+ }
3354+ allGlobals[global->name ] = &it->second ;
3355+ }
3356+ }
3357+ }
3358+
33243359 void initializeTableContents () {
33253360 for (auto & table : wasm.tables ) {
33263361 if (table->type .isNullable ()) {
@@ -3511,20 +3546,8 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
35113546 SmallVector<std::pair<WasmException, Name>, 4 > exceptionStack;
35123547
35133548protected:
3514- // Returns a reference to the current value of a potentially imported global.
3515- Literals& getGlobal (Name name) {
3516- auto * inst = self ();
3517- auto * global = inst->wasm .getGlobal (name);
3518- while (global->imported ()) {
3519- inst = inst->linkedInstances .at (global->module ).get ();
3520- Export* globalExport = inst->wasm .getExport (global->base );
3521- global = inst->wasm .getGlobal (*globalExport->getInternalName ());
3522- }
3523-
3524- return inst->globals [global->name ];
3525- }
3526-
3527- // As above, but for a function.
3549+ // Returns a reference to the current value of a potentially imported
3550+ // function.
35283551 Literal getFunction (Name name) {
35293552 auto * inst = self ();
35303553 auto * func = inst->wasm .getFunction (name);
@@ -3846,13 +3869,13 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
38463869
38473870 Flow visitGlobalGet (GlobalGet* curr) {
38483871 auto name = curr->name ;
3849- return getGlobal (name);
3872+ return *allGlobals. at (name);
38503873 }
38513874 Flow visitGlobalSet (GlobalSet* curr) {
38523875 auto name = curr->name ;
38533876 VISIT (flow, curr->value )
38543877
3855- getGlobal (name) = flow.values ;
3878+ *allGlobals. at (name) = flow.values ;
38563879 return Flow ();
38573880 }
38583881
@@ -5055,6 +5078,7 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
50555078
50565079 ExternalInterface* externalInterface;
50575080 std::map<Name, std::shared_ptr<SubType>> linkedInstances;
5081+ std::shared_ptr<ImportResolver> importResolver;
50585082};
50595083
50605084class ModuleRunner : public ModuleRunnerBase <ModuleRunner> {
@@ -5063,7 +5087,15 @@ class ModuleRunner : public ModuleRunnerBase<ModuleRunner> {
50635087 Module& wasm,
50645088 ExternalInterface* externalInterface,
50655089 std::map<Name, std::shared_ptr<ModuleRunner>> linkedInstances = {})
5066- : ModuleRunnerBase(wasm, externalInterface, linkedInstances) {}
5090+ : ModuleRunnerBase(
5091+ wasm,
5092+ externalInterface,
5093+ std::make_shared<ChainedImportResolver>(
5094+ std::initializer_list<std::shared_ptr<ImportResolver>>{
5095+ std::make_shared<SpecTestModuleImportResolver>(),
5096+ std::make_shared<LinkedInstancesImportResolver<ModuleRunner>>(
5097+ linkedInstances)}),
5098+ linkedInstances) {}
50675099
50685100 Literal makeFuncData (Name name, Type type) {
50695101 // As the super's |makeFuncData|, but here we also provide a way to
0 commit comments