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,22 @@ 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),
3190+ linkedInstances (std::move(linkedInstances_)),
3191+ importResolver (std::move(importResolver)) {
31893192 // Set up a single shared CurrContinuations for all these linked instances,
31903193 // reusing one if it exists.
31913194 std::shared_ptr<ContinuationStore> shared;
@@ -3208,16 +3211,11 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
32083211 // (This is separate from the constructor so that it does not occur
32093212 // synchronously, which makes some code patterns harder to write.)
32103213 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-
32183214 // initialize the rest of the external interface
32193215 externalInterface->init (wasm, *self ());
32203216
3217+ initializeGlobals ();
3218+
32213219 initializeTableContents ();
32223220 initializeMemoryContents ();
32233221
@@ -3254,20 +3252,30 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
32543252 func->type );
32553253 }
32563254
3257- // get an exported global
3258- Literals getExportedGlobal (Name name) {
3255+ std::optional<Literals*> getExportedGlobal (Name name) {
32593256 Export* export_ = wasm.getExportOrNull (name);
32603257 if (!export_ || export_->kind != ExternalKind::Global) {
3261- externalInterface-> trap ( " getExport external not found " ) ;
3258+ return std:: nullopt ;
32623259 }
32633260 Name internalName = *export_->getInternalName ();
3264- auto iter = globals .find (internalName);
3265- if (iter == globals .end ()) {
3266- externalInterface-> trap ( " getExport internal not found " ) ;
3261+ auto iter = allGlobals .find (internalName);
3262+ if (iter == allGlobals .end ()) {
3263+ return std:: nullopt ;
32673264 }
32683265 return iter->second ;
32693266 }
32703267
3268+ Literals& getExportedGlobalOrTrap (Name name) {
3269+ auto global = getExportedGlobal (name);
3270+ if (!global.has_value ()) {
3271+ externalInterface->trap ((std::stringstream ()
3272+ << " getExportedGlobal: export " << name
3273+ << " not found." )
3274+ .str ());
3275+ }
3276+ return **global;
3277+ }
3278+
32713279 Tag* getExportedTag (Name name) {
32723280 Export* export_ = wasm.getExportOrNull (name);
32733281 if (!export_ || export_->kind != ExternalKind::Tag) {
@@ -3321,6 +3329,34 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
33213329 return TableInstanceInfo{self (), name};
33223330 }
33233331
3332+ void initializeGlobals () {
3333+ for (auto & global : wasm.globals ) {
3334+ if (global->imported ()) {
3335+ QualifiedName name{global->module , global->base };
3336+ auto importedGlobal = importResolver->getGlobal (name, global->type );
3337+ if (!importedGlobal) {
3338+ externalInterface->trap (
3339+ (std::stringstream () << " Imported global " << name << " not found." )
3340+ .str ());
3341+ }
3342+ allGlobals[global->name ] = *importedGlobal;
3343+ } else {
3344+ Literals init = self ()->visit (global->init ).values ;
3345+ auto [it, inserted] = definedGlobals.emplace (global->name , init);
3346+
3347+ // This was likely checked during parsing or validation
3348+ if (!inserted) {
3349+ externalInterface->trap (
3350+ (std::stringstream ()
3351+ << " Global: " << std::quoted (global->name .toString ())
3352+ << " was defined twice." )
3353+ .str ());
3354+ }
3355+ allGlobals[global->name ] = &it->second ;
3356+ }
3357+ }
3358+ }
3359+
33243360 void initializeTableContents () {
33253361 for (auto & table : wasm.tables ) {
33263362 if (table->type .isNullable ()) {
@@ -3511,20 +3547,8 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
35113547 SmallVector<std::pair<WasmException, Name>, 4 > exceptionStack;
35123548
35133549protected:
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.
3550+ // Returns a reference to the current value of a potentially imported
3551+ // function.
35283552 Literal getFunction (Name name) {
35293553 auto * inst = self ();
35303554 auto * func = inst->wasm .getFunction (name);
@@ -3846,13 +3870,13 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
38463870
38473871 Flow visitGlobalGet (GlobalGet* curr) {
38483872 auto name = curr->name ;
3849- return getGlobal (name);
3873+ return *allGlobals. at (name);
38503874 }
38513875 Flow visitGlobalSet (GlobalSet* curr) {
38523876 auto name = curr->name ;
38533877 VISIT (flow, curr->value )
38543878
3855- getGlobal (name) = flow.values ;
3879+ *allGlobals. at (name) = flow.values ;
38563880 return Flow ();
38573881 }
38583882
@@ -5055,6 +5079,7 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
50555079
50565080 ExternalInterface* externalInterface;
50575081 std::map<Name, std::shared_ptr<SubType>> linkedInstances;
5082+ std::shared_ptr<ImportResolver> importResolver;
50585083};
50595084
50605085class ModuleRunner : public ModuleRunnerBase <ModuleRunner> {
@@ -5063,7 +5088,12 @@ class ModuleRunner : public ModuleRunnerBase<ModuleRunner> {
50635088 Module& wasm,
50645089 ExternalInterface* externalInterface,
50655090 std::map<Name, std::shared_ptr<ModuleRunner>> linkedInstances = {})
5066- : ModuleRunnerBase(wasm, externalInterface, linkedInstances) {}
5091+ : ModuleRunnerBase(
5092+ wasm,
5093+ externalInterface,
5094+ std::make_shared<LinkedInstancesImportResolver<ModuleRunner>>(
5095+ linkedInstances),
5096+ linkedInstances) {}
50675097
50685098 Literal makeFuncData (Name name, Type type) {
50695099 // As the super's |makeFuncData|, but here we also provide a way to
0 commit comments