/// <summary> /// Instantiates the tables in the given WebAssembly file. /// </summary> /// <param name="File">The file whose tables are to be instantiated.</param> private void InstantiateTables(WasmFile File) { // Create module-defined tables. var allTableSections = File.GetSections <TableSection>(); for (int i = 0; i < allTableSections.Count; i++) { foreach (var tableSpec in allTableSections[i].Tables) { definedTables.Add(new FunctionTable(tableSpec.Limits)); } } // Initialize tables by applying the segments defined by element sections. var allElementSections = File.GetSections <ElementSection>(); for (int i = 0; i < allElementSections.Count; i++) { foreach (var segment in allElementSections[i].Segments) { var table = Tables[(int)segment.TableIndex]; var evalOffset = Evaluate <int>(segment.Offset); for (int j = 0; j < segment.Elements.Count; j++) { table[(uint)(evalOffset + j)] = definedFuncs[(int)segment.Elements[j]]; } } } }
private void InstantiateMemories(WasmFile File) { // Create module-defined memories. var allMemorySections = File.GetSections <MemorySection>(); for (int i = 0; i < allMemorySections.Count; i++) { var memorySection = allMemorySections[i]; foreach (var memorySpec in memorySection.Memories) { definedMemories.Add(new LinearMemory(memorySpec.Limits)); } } // Initialize memories by applying the segments defined by data sections. var allDataSections = File.GetSections <DataSection>(); for (int i = 0; i < allDataSections.Count; i++) { var dataSection = allDataSections[i]; foreach (var segment in dataSection.Segments) { var memoryView = Memories[(int)segment.MemoryIndex].Int8; var evalOffset = Evaluate <int>(segment.Offset); for (int j = 0; j < segment.Data.Length; j++) { memoryView[(uint)(evalOffset + j)] = (sbyte)segment.Data[j]; } } } }
/// <summary> /// Instantiates all function definitions from the given WebAssembly file. /// </summary> /// <param name="File">A WebAssembly file.</param> /// <param name="FunctionTypes">The list of all function types declared by the WebAssembly file.</param> private void InstantiateFunctionDefs(WasmFile File, List <FunctionType> FunctionTypes) { var funcSignatures = new List <FunctionType>(); var funcBodies = new List <FunctionBody>(); var allFuncSections = File.GetSections <FunctionSection>(); for (int i = 0; i < allFuncSections.Count; i++) { foreach (var funcSpec in allFuncSections[i].FunctionTypes) { funcSignatures.Add(FunctionTypes[(int)funcSpec]); } } var allCodeSections = File.GetSections <CodeSection>(); for (int i = 0; i < allCodeSections.Count; i++) { funcBodies.AddRange(allCodeSections[i].Bodies); } if (funcSignatures.Count != funcBodies.Count) { throw new WasmException( "Function declaration/definition count mismatch: module declares " + funcSignatures.Count + " functions and defines " + funcBodies.Count + "."); } for (int i = 0; i < funcSignatures.Count; i++) { DefineFunction(funcSignatures[i], funcBodies[i]); } }
/// <summary> /// Exports values specified by the given WebAssembly file. /// </summary> /// <param name="File">The file that specifies which values are to be exported and how.</param> private void RegisterExports(WasmFile File) { var allExportSections = File.GetSections <ExportSection>(); for (int i = 0; i < allExportSections.Count; i++) { foreach (var export in allExportSections[i].Exports) { switch (export.Kind) { case ExternalKind.Memory: expMemories[export.Name] = Memories[(int)export.Index]; break; case ExternalKind.Global: expGlobals[export.Name] = Globals[(int)export.Index]; break; case ExternalKind.Function: expFuncs[export.Name] = Functions[(int)export.Index]; break; case ExternalKind.Table: expTables[export.Name] = Tables[(int)export.Index]; break; default: throw new WasmException("Unknown export kind: " + export.Kind); } } } }
private void InstantiateMemories(WasmFile file, uint maxMemorySize) { // Create module-defined memories. var allMemorySections = file.GetSections <MemorySection>(); for (int i = 0; i < allMemorySections.Count; i++) { var memorySection = allMemorySections[i]; foreach (var memorySpec in memorySection.Memories) { if (maxMemorySize == 0) { definedMemories.Add(new LinearMemory(memorySpec.Limits)); } else { definedMemories.Add( new LinearMemory( new ResizableLimits( memorySpec.Limits.Initial, memorySpec.Limits.HasMaximum ? Math.Min(memorySpec.Limits.Maximum.Value, maxMemorySize) : maxMemorySize))); } } } // Initialize memories by applying the segments defined by data sections. var allDataSections = file.GetSections <DataSection>(); for (int i = 0; i < allDataSections.Count; i++) { var dataSection = allDataSections[i]; foreach (var segment in dataSection.Segments) { var memoryView = Memories[(int)segment.MemoryIndex].Int8; var evalOffset = Evaluate <int>(segment.Offset); for (int j = 0; j < segment.Data.Length; j++) { memoryView[(uint)(evalOffset + j)] = (sbyte)segment.Data[j]; } } } }
/// <summary> /// Uses the given importer to resolve all imported values. /// </summary> /// <param name="Importer">The importer.</param> private void ResolveImports( WasmFile File, IImporter Importer, List <FunctionType> FunctionTypes) { var allImportSections = File.GetSections <ImportSection>(); for (int i = 0; i < allImportSections.Count; i++) { var importSection = allImportSections[i]; foreach (var import in importSection.Imports) { if (import is ImportedMemory) { var memory = Importer.ImportMemory((ImportedMemory)import); if (memory == null) { ThrowCannotResolveImport(import, "linear memory"); } definedMemories.Add(memory); } else if (import is ImportedGlobal) { var globalVar = Importer.ImportGlobal((ImportedGlobal)import); if (globalVar == null) { ThrowCannotResolveImport(import, "global variable"); } definedGlobals.Add(globalVar); } else if (import is ImportedFunction) { var funcImport = (ImportedFunction)import; var funcDef = Importer.ImportFunction(funcImport, FunctionTypes[(int)funcImport.TypeIndex]); if (funcDef == null) { ThrowCannotResolveImport(import, "function"); } definedFuncs.Add(funcDef); } else if (import is ImportedTable) { var table = Importer.ImportTable((ImportedTable)import); if (table == null) { ThrowCannotResolveImport(import, "table"); } definedTables.Add(table); } else { throw new WasmException("Unknown import type: " + import.ToString()); } } } }
/// <summary> /// Gets a list of all function types declared by the given WebAssembly file. /// </summary> /// <param name="File">The WebAssembly file to examine.</param> /// <returns>The list of function types.</returns> private static List <FunctionType> GetFunctionTypes(WasmFile File) { var allFuncTypes = new List <FunctionType>(); var allTypeSections = File.GetSections <TypeSection>(); for (int i = 0; i < allTypeSections.Count; i++) { allFuncTypes.AddRange(allTypeSections[i].FunctionTypes); } return(allFuncTypes); }
/// <summary> /// Rewrites function type references in the given WebAssembly file /// by replacing keys from the rewrite map with their corresponding /// values. /// </summary> /// <param name="File">The WebAssembly file to rewrite.</param> /// <param name="RewriteMap">A mapping of original type indices to new type indices.</param> public static void RewriteFunctionTypeReferences( this WasmFile File, IReadOnlyDictionary <uint, uint> RewriteMap) { // Type references occur only in the import and function sections. var importSections = File.GetSections <ImportSection>(); for (int i = 0; i < importSections.Count; i++) { var importSec = importSections[i]; for (int j = 0; j < importSec.Imports.Count; j++) { var importDecl = importSec.Imports[j] as ImportedFunction; uint newIndex; if (importDecl != null && RewriteMap.TryGetValue(importDecl.TypeIndex, out newIndex)) { importDecl.TypeIndex = newIndex; } } } var funcSections = File.GetSections <FunctionSection>(); for (int i = 0; i < funcSections.Count; i++) { var funcSec = funcSections[i]; for (int j = 0; j < funcSec.FunctionTypes.Count; j++) { uint newIndex; if (RewriteMap.TryGetValue(funcSec.FunctionTypes[j], out newIndex)) { funcSec.FunctionTypes[j] = newIndex; } } } }
/// <summary> /// Instantiates all function definitions from the given WebAssembly file. /// </summary> /// <param name="file">A WebAssembly file.</param> /// <param name="compiler">A compiler to use for instantiating function definitions.</param> /// <param name="functionTypes">The list of all function types declared by the WebAssembly file.</param> private void InstantiateFunctionDefs(WasmFile file, ModuleCompiler compiler, List <FunctionType> functionTypes) { var funcSignatures = new List <FunctionType>(); var funcBodies = new List <FunctionBody>(); var allFuncSections = file.GetSections <FunctionSection>(); for (int i = 0; i < allFuncSections.Count; i++) { foreach (var funcSpec in allFuncSections[i].FunctionTypes) { funcSignatures.Add(functionTypes[(int)funcSpec]); } } var allCodeSections = file.GetSections <CodeSection>(); for (int i = 0; i < allCodeSections.Count; i++) { funcBodies.AddRange(allCodeSections[i].Bodies); } if (funcSignatures.Count != funcBodies.Count) { throw new WasmException( "Function declaration/definition count mismatch: module declares " + funcSignatures.Count + " functions and defines " + funcBodies.Count + "."); } compiler.Initialize(this, definedFuncs.Count, funcSignatures); for (int i = 0; i < funcSignatures.Count; i++) { DefineFunction(compiler.Compile(i, funcBodies[i])); } compiler.Finish(); }
private void InstantiateGlobals(WasmFile File) { // Create module-defined globals. var allGlobalSections = File.GetSections <GlobalSection>(); for (int i = 0; i < allGlobalSections.Count; i++) { var globalSection = allGlobalSections[i]; foreach (var globalSpec in globalSection.GlobalVariables) { definedGlobals.Add( Variable.Create <object>( globalSpec.Type.ContentType, globalSpec.Type.IsMutable, Evaluate <object>(globalSpec.InitialValue))); } } }