@@ -126,7 +126,7 @@ namespace Js
126126 {
127127 Wasm::WasmDataSegment* segment = wasmModule->GetDataSeg (iSeg);
128128 Assert (segment != nullptr );
129- const uint32 offset = segment->getDestAddr ();
129+ const uint32 offset = segment->getDestAddr (wasmModule );
130130 const uint32 size = segment->getSourceSize ();
131131 if (offset > maxSize || UInt32Math::Add (offset, size) > maxSize)
132132 {
@@ -252,17 +252,86 @@ namespace Js
252252 {
253253 PropertyRecord const * propertyRecord = nullptr ;
254254 ctx->GetOrAddPropertyRecord (funcExport->name , funcExport->nameLength , &propertyRecord);
255- Var funcObj = GetFunctionObjFromFunctionIndex (wasmModule, ctx, funcExport->funcIndex , localModuleFunctions, importFunctions);
256- if (!funcObj)
255+
256+ Var obj = ctx->GetLibrary ()->GetUndefined ();
257+ switch (funcExport->kind )
257258 {
258- funcObj = ctx->GetLibrary ()->GetUndefined ();
259+ case Wasm::ExternalKinds::Function:
260+
261+ obj = GetFunctionObjFromFunctionIndex (wasmModule, ctx, funcExport->funcIndex , localModuleFunctions, importFunctions);
262+ break ;
263+ case Wasm::ExternalKinds::Global:
264+ Wasm::WasmGlobal* global = wasmModule->globals .Item (funcExport->funcIndex );
265+ Assert (global->GetReferenceType () == Wasm::WasmGlobal::Const); // every global has to be resolved by this point
266+
267+ if (global->GetMutability ())
268+ {
269+ throw Wasm::WasmCompilationException (_u (" global %d is mutable. Exporting mutable globals isn't supported" ), iExport);
270+ }
271+
272+ switch (global->GetType ())
273+ {
274+ case Wasm::WasmTypes::I32:
275+ obj = JavascriptNumber::ToVar (global->cnst .i32 , ctx);
276+ break ;
277+ case Wasm::WasmTypes::F32:
278+ obj = JavascriptNumber::New ((double )global->cnst .f32 , ctx);
279+ break ;
280+ case Wasm::WasmTypes::F64:
281+ obj = JavascriptNumber::New (global->cnst .f64 , ctx);
282+ break ;
283+ case Wasm::WasmTypes::I64:
284+ default :
285+ Assert (UNREACHED);
286+ break ;
287+ }
259288 }
260- JavascriptOperators::OP_SetProperty (exportsNamespace, propertyRecord->GetPropertyId (), funcObj , ctx);
289+ JavascriptOperators::OP_SetProperty (exportsNamespace, propertyRecord->GetPropertyId (), obj , ctx);
261290 }
262291 }
263292 }
264293
265- void WasmLibrary::WasmLoadImports (Wasm::WasmModule * wasmModule, ScriptContext* ctx, Var* importFunctions, Var ffi)
294+ static Var GetImportVariable (Wasm::WasmImport* wi, ScriptContext* ctx, Var ffi)
295+ {
296+ PropertyRecord const * modPropertyRecord = nullptr ;
297+ char16* modName = wi->modName ;
298+ uint32 modNameLen = wi->modNameLen ;
299+ ctx->GetOrAddPropertyRecord (modName, modNameLen, &modPropertyRecord);
300+ Var modProp = JavascriptOperators::OP_GetProperty (ffi, modPropertyRecord->GetPropertyId (), ctx);
301+
302+
303+
304+ char16* name = wi->fnName ;
305+ uint32 nameLen = wi->fnNameLen ;
306+ Var prop = nullptr ;
307+ if (nameLen > 0 )
308+ {
309+ PropertyRecord const * propertyRecord = nullptr ;
310+ ctx->GetOrAddPropertyRecord (name, nameLen, &propertyRecord);
311+
312+ if (!JavascriptObject::Is (modProp))
313+ {
314+ throw Wasm::WasmCompilationException (_u (" Import module %s is invalid" ), modName);
315+ }
316+ prop = JavascriptOperators::OP_GetProperty (modProp, propertyRecord->GetPropertyId (), ctx);
317+ }
318+ else
319+ {
320+ // Use only first level if name is missing
321+ prop = modProp;
322+ }
323+
324+ return prop;
325+ }
326+
327+ template <typename T>
328+ void static SetGlobalValue (Var moduleEnv, uint offset, T val)
329+ {
330+ T* slot = (T*)moduleEnv + offset;
331+ *slot = val;
332+ }
333+
334+ void WasmLibrary::WasmLoadImports (Wasm::WasmModule * wasmModule, ScriptContext* ctx, Var* importFunctions, Var moduleEnv, Var ffi)
266335 {
267336 const uint32 importCount = wasmModule->GetImportCount ();
268337 if (importCount > 0 && (!ffi || !JavascriptObject::Is (ffi)))
@@ -271,37 +340,111 @@ namespace Js
271340 }
272341 for (uint32 i = 0 ; i < importCount; ++i)
273342 {
274- PropertyRecord const * modPropertyRecord = nullptr ;
275- PropertyRecord const * propertyRecord = nullptr ;
343+ Var prop = GetImportVariable (wasmModule->GetFunctionImport (i), ctx, ffi);
344+ if (!JavascriptFunction::Is (prop))
345+ {
346+ throw Wasm::WasmCompilationException (_u (" Import function %s.%s is invalid" ), wasmModule->GetFunctionImport (i)->modName , wasmModule->GetFunctionImport (i)->fnName );
347+ }
348+ importFunctions[i] = prop;
349+ }
350+ }
351+
352+ void WasmLibrary::WasmLoadGlobals (Wasm::WasmModule * wasmModule, ScriptContext* ctx, Var moduleEnv, Var ffi)
353+ {
354+ uint i = 0 ;
355+ uint count = (uint) wasmModule->globals .Count ();
356+ while (i < count && wasmModule->globals .Item (i)->GetReferenceType () == Wasm::WasmGlobal::ImportedReference)
357+ {
358+ Wasm::WasmGlobal* global = wasmModule->globals .Item (i);
359+ Var prop = GetImportVariable (global->importVar , ctx, ffi);
276360
277- char16* modName = wasmModule->GetFunctionImport (i)->modName ;
278- uint32 modNameLen = wasmModule->GetFunctionImport (i)->modNameLen ;
279- ctx->GetOrAddPropertyRecord (modName, modNameLen, &modPropertyRecord);
280- Var modProp = JavascriptOperators::OP_GetProperty (ffi, modPropertyRecord->GetPropertyId (), ctx);
361+ uint offset = wasmModule->GetOffsetForGlobal (global);
362+ global->SetReferenceType (Wasm::WasmGlobal::Const);
281363
282- char16* name = wasmModule->GetFunctionImport (i)->fnName ;
283- uint32 nameLen = wasmModule->GetFunctionImport (i)->fnNameLen ;
284- Var prop = nullptr ;
285- if (nameLen > 0 )
364+ if (!JavascriptNumber::Is (prop) && !TaggedInt::Is (prop))
286365 {
287- ctx->GetOrAddPropertyRecord (name, nameLen, &propertyRecord);
366+ throw Wasm::WasmCompilationException (_u (" Import global %s.%s (%d) isn't a valid javascript number" ), global->importVar ->modName , global->importVar ->fnName , i);
367+ }
288368
289- if (!JavascriptObject::Is (modProp))
290- {
291- throw Wasm::WasmCompilationException (_u (" Import module %s is invalid" ), modName);
292- }
293- prop = JavascriptOperators::OP_GetProperty (modProp, propertyRecord->GetPropertyId (), ctx);
369+ switch (global->GetType ())
370+ {
371+ case Wasm::WasmTypes::I32:
372+ {
373+
374+ int val = JavascriptConversion::ToInt32 (prop, ctx);
375+ global->cnst .i32 = val; // resolve global to const
376+ SetGlobalValue (moduleEnv, offset, val);
377+ break ;
378+ }
379+ case Wasm::WasmTypes::F32:
380+ {
381+ float val = (float ) JavascriptConversion::ToNumber (prop, ctx);
382+ global->cnst .f32 = val;
383+ SetGlobalValue (moduleEnv, offset, val);
384+ }
385+ case Wasm::WasmTypes::F64:
386+ {
387+ double val = JavascriptConversion::ToNumber (prop, ctx);
388+ global->cnst .f64 = val;
389+ SetGlobalValue (moduleEnv, offset, val);
390+ break ;
391+ }
392+ case Wasm::WasmTypes::I64:
393+ default :
394+ Assert (UNREACHED);
395+ break ;
396+
397+ }
398+ i++;
399+ }
400+
401+
402+ for (; i < count; i++)
403+ {
404+ Wasm::WasmGlobal* global = wasmModule->globals .Item (i);
405+
406+ uint offset = wasmModule->GetOffsetForGlobal (global);
407+ Wasm::WasmGlobal* sourceGlobal = nullptr ;
408+ if (global->GetReferenceType () == Wasm::WasmGlobal::Const)
409+ {
410+ sourceGlobal = global;
294411 }
295412 else
296413 {
297- // Use only first level if name is missing
298- prop = modProp;
414+ sourceGlobal = wasmModule->globals .Item (global->var .num );
415+ Assert (sourceGlobal->GetReferenceType () != Wasm::WasmGlobal::ImportedReference); // no imported globals at this point
416+ if (sourceGlobal->GetReferenceType () != Wasm::WasmGlobal::Const)
417+ {
418+ throw Wasm::WasmCompilationException (_u (" Global %d is initialized with global %d "
419+ " which is not a const. Forward references aren't supported!" ), i, global->var .num );
420+ }
421+ global->SetReferenceType (Wasm::WasmGlobal::Const); // resolve global to const
422+ global->cnst = sourceGlobal->cnst ;
423+
424+ Assert (sourceGlobal->GetReferenceType () == Wasm::WasmGlobal::Const);
425+ if (sourceGlobal->GetType () != global->GetType ())
426+ {
427+ throw Wasm::WasmCompilationException (_u (" Type mismatch between %d and %d" ), i, global->var .num );
428+ }
299429 }
300- if (!JavascriptFunction::Is (prop))
430+
431+ switch (sourceGlobal->GetType ())
301432 {
302- throw Wasm::WasmCompilationException (_u (" Import function %s.%s is invalid" ), modName, name);
433+ case Wasm::WasmTypes::I32:
434+ SetGlobalValue (moduleEnv, offset, sourceGlobal->cnst .i32 );
435+ break ;
436+ case Wasm::WasmTypes::F32:
437+ SetGlobalValue (moduleEnv, offset, sourceGlobal->cnst .f32 );
438+ break ;
439+ case Wasm::WasmTypes::F64:
440+ SetGlobalValue (moduleEnv, offset, sourceGlobal->cnst .f64 );
441+ break ;
442+ case Wasm::WasmTypes::I64:
443+ default :
444+ Assert (UNREACHED);
445+ break ;
303446 }
304- importFunctions[i] = prop;
447+
305448 }
306449 }
307450
@@ -389,13 +532,15 @@ namespace Js
389532 exportObj = JavascriptOperators::NewJavascriptObjectNoArg (scriptContext);
390533 Var* localModuleFunctions = moduleEnvironmentPtr + wasmModule->GetFuncOffset ();
391534
535+ WasmLoadGlobals (wasmModule, scriptContext, moduleEnvironmentPtr, ffi);
392536 WasmLoadDataSegs (wasmModule, heap, scriptContext);
393537
394538 bool hasAnyLazyTraps = false ;
395539 WasmLoadFunctions (wasmModule, scriptContext, moduleEnvironmentPtr, &exportObj, localModuleFunctions, &hasAnyLazyTraps);
396-
540+
397541 Var* importFunctions = moduleEnvironmentPtr + wasmModule->GetImportFuncOffset ();
398- WasmLoadImports (wasmModule, scriptContext, importFunctions, ffi);
542+ WasmLoadImports (wasmModule, scriptContext, importFunctions, moduleEnvironmentPtr, ffi);
543+
399544
400545 Js::Var exportsNamespace = JavascriptOperators::NewJavascriptObjectNoArg (scriptContext);
401546 WasmBuildObject (wasmModule, scriptContext, exportsNamespace, heap, &exportObj, &hasAnyLazyTraps, localModuleFunctions, importFunctions);
0 commit comments