@@ -127,8 +127,11 @@ static Index STACK_UPPER_LIMIT = STACK_START + STACK_SIZE;
127127class EvallingModuleInstance
128128 : public ModuleInstanceBase<EvallingGlobalManager, EvallingModuleInstance> {
129129public:
130- EvallingModuleInstance (Module& wasm, ExternalInterface* externalInterface)
131- : ModuleInstanceBase(wasm, externalInterface) {
130+ EvallingModuleInstance (Module& wasm,
131+ ExternalInterface* externalInterface,
132+ std::map<Name, std::shared_ptr<EvallingModuleInstance>>
133+ linkedInstances_ = {})
134+ : ModuleInstanceBase(wasm, externalInterface, linkedInstances_) {
132135 // if any global in the module has a non-const constructor, it is using a
133136 // global import, which we don't have, and is illegal to use
134137 ModuleUtils::iterDefinedGlobals (wasm, [&](Global* global) {
@@ -165,41 +168,103 @@ class EvallingModuleInstance
165168 }
166169};
167170
171+ // Build an artificial `env` module based on a module's imports, so that the
172+ // interpreter can use correct object instances. It initializes usable global
173+ // imports, and fills the rest with fake values since those are dangerous to
174+ // use. we will fail if dangerous globals are used.
175+ std::unique_ptr<Module> buildEnvModule (Module& wasm) {
176+ auto env = std::make_unique<Module>();
177+ env->name = " env" ;
178+
179+ // create empty functions with similar signature
180+ ModuleUtils::iterImportedFunctions (wasm, [&](Function* func) {
181+ if (func->module == " env" ) {
182+ Builder builder (*env);
183+ auto * copied = ModuleUtils::copyFunction (func, *env);
184+ copied->module = Name ();
185+ copied->base = Name ();
186+ copied->body = builder.makeUnreachable ();
187+ env->addExport (
188+ builder.makeExport (func->base , copied->name , ExternalKind::Function));
189+ }
190+ });
191+
192+ // create tables with similar initial and max values
193+ ModuleUtils::iterImportedTables (wasm, [&](Table* table) {
194+ if (table->module == " env" ) {
195+ auto * copied = ModuleUtils::copyTable (table, *env);
196+ copied->module = Name ();
197+ copied->base = Name ();
198+ env->addExport (Builder (*env).makeExport (
199+ table->base , copied->name , ExternalKind::Table));
200+ }
201+ });
202+
203+ ModuleUtils::iterImportedGlobals (wasm, [&](Global* global) {
204+ if (global->module == " env" ) {
205+ auto * copied = ModuleUtils::copyGlobal (global, *env);
206+ copied->module = Name ();
207+ copied->base = Name ();
208+
209+ Builder builder (*env);
210+ if (global->base == STACKTOP || global->base == STACK_MAX) {
211+ copied->init = builder.makeConst (STACK_START);
212+ } else {
213+ copied->init = builder.makeConst (Literal::makeZero (global->type ));
214+ }
215+ env->addExport (
216+ builder.makeExport (global->base , copied->name , ExternalKind::Global));
217+ }
218+ });
219+
220+ // create an exported memory with the same initial and max size
221+ ModuleUtils::iterImportedMemories (wasm, [&](Memory* memory) {
222+ if (memory->module == " env" ) {
223+ env->memory .name = wasm.memory .name ;
224+ env->memory .exists = true ;
225+ env->memory .initial = memory->initial ;
226+ env->memory .max = memory->max ;
227+ env->memory .shared = memory->shared ;
228+ env->memory .indexType = memory->indexType ;
229+ env->addExport (Builder (*env).makeExport (
230+ wasm.memory .base , wasm.memory .name , ExternalKind::Memory));
231+ }
232+ });
233+
234+ return env;
235+ }
236+
168237struct CtorEvalExternalInterface : EvallingModuleInstance::ExternalInterface {
169238 Module* wasm;
170239 EvallingModuleInstance* instance;
240+ std::map<Name, std::shared_ptr<EvallingModuleInstance>> linkedInstances;
241+
242+ CtorEvalExternalInterface (
243+ std::map<Name, std::shared_ptr<EvallingModuleInstance>> linkedInstances_ =
244+ {}) {
245+ linkedInstances.swap (linkedInstances_);
246+ }
171247
172248 void init (Module& wasm_, EvallingModuleInstance& instance_) override {
173249 wasm = &wasm_;
174250 instance = &instance_;
175251 }
176252
177253 void importGlobals (EvallingGlobalManager& globals, Module& wasm_) override {
178- // fill usable values for stack imports, and globals initialized to them
179- ImportInfo imports (wasm_);
180- if (auto * stackTop = imports.getImportedGlobal (ENV, STACKTOP)) {
181- globals[stackTop->name ] = {Literal (int32_t (STACK_START))};
182- if (auto * stackTop =
183- GlobalUtils::getGlobalInitializedToImport (wasm_, ENV, STACKTOP)) {
184- globals[stackTop->name ] = {Literal (int32_t (STACK_START))};
185- }
186- }
187- if (auto * stackMax = imports.getImportedGlobal (ENV, STACK_MAX)) {
188- globals[stackMax->name ] = {Literal (int32_t (STACK_START))};
189- if (auto * stackMax =
190- GlobalUtils::getGlobalInitializedToImport (wasm_, ENV, STACK_MAX)) {
191- globals[stackMax->name ] = {Literal (int32_t (STACK_START))};
192- }
193- }
194- // fill in fake values for everything else, which is dangerous to use
195- ModuleUtils::iterDefinedGlobals (wasm_, [&](Global* defined ) {
196- if (globals.find (defined ->name ) == globals.end ()) {
197- globals[defined ->name ] = Literal::makeZeros (defined ->type );
198- }
199- });
200- ModuleUtils::iterImportedGlobals (wasm_, [&](Global* import ) {
201- if (globals.find (import ->name ) == globals.end ()) {
202- globals[import ->name ] = Literal::makeZeros (import ->type );
254+ ModuleUtils::iterImportedGlobals (wasm_, [&](Global* global) {
255+ auto it = linkedInstances.find (global->module );
256+ if (it != linkedInstances.end ()) {
257+ auto * inst = it->second .get ();
258+ auto * globalExport = inst->wasm .getExportOrNull (global->base );
259+ if (!globalExport) {
260+ throw FailToEvalException (std::string (" importGlobals: " ) +
261+ global->module .str + " ." +
262+ global->base .str );
263+ }
264+ globals[global->name ] = inst->globals [globalExport->value ];
265+ } else {
266+ throw FailToEvalException (std::string (" importGlobals: " ) +
267+ global->module .str + " ." + global->base .str );
203268 }
204269 });
205270 }
@@ -368,14 +433,25 @@ struct CtorEvalExternalInterface : EvallingModuleInstance::ExternalInterface {
368433};
369434
370435void evalCtors (Module& wasm, std::vector<std::string> ctors) {
371- CtorEvalExternalInterface interface;
436+ // build and link the env module
437+ auto envModule = buildEnvModule (wasm);
438+ CtorEvalExternalInterface envInterface;
439+ auto envInstance =
440+ std::make_shared<EvallingModuleInstance>(*envModule, &envInterface);
441+ envInstance->setupEnvironment ();
442+
443+ std::map<Name, std::shared_ptr<EvallingModuleInstance>> linkedInstances;
444+ linkedInstances[" env" ] = envInstance;
445+
446+ CtorEvalExternalInterface interface (linkedInstances);
372447 try {
373448 // flatten memory, so we do not depend on the layout of data segments
374449 if (!MemoryUtils::flatten (wasm.memory )) {
375450 Fatal () << " ...stopping since could not flatten memory\n " ;
376451 }
452+
377453 // create an instance for evalling
378- EvallingModuleInstance instance (wasm, &interface);
454+ EvallingModuleInstance instance (wasm, &interface, linkedInstances );
379455 // set up the stack area and other environment details
380456 instance.setupEnvironment ();
381457 // we should not add new globals from here on; as a result, using
0 commit comments