RyanLamansky / dotnet-webassembly

Create, read, modify, write and execute WebAssembly (WASM) files from .NET-based applications.
Apache License 2.0
789 stars 74 forks source link

Issue with function out index #39

Open bbday opened 2 years ago

bbday commented 2 years ago

I have issue with this wasm link bellow:

var module = Module.ReadFromBinary("module.wasm");
            //var module = GenerateExample();

            foreach (var export in module.Exports)
            {
                static string WebAssemblyValueTypeToNative(WebAssemblyValueType type) => type switch
                {
                    WebAssemblyValueType.Int32 => "int",
                    WebAssemblyValueType.Int64 => "long",
                    WebAssemblyValueType.Float32 => "float",
                    WebAssemblyValueType.Float64 => "double",
                    _ => throw new NotSupportedException(),
                };

                switch (export.Kind)
                {
                    case ExternalKind.Function:
                        // TODO: Account for the indexes of imported functions--first internal function's index is 1 after the last imported.
                        var signature = module.Types[(int)module.Functions[(int)export.Index].Type];
                        Console.Write(indent);
                        Console.Write("public abstract ");
                        Console.Write(signature.Returns.Count == 0 ? "void" : WebAssemblyValueTypeToNative(signature.Returns[0]));
                        Console.Write(' ');
                        Console.Write(export.Name);
                        Console.Write('(');
                        Console.Write(string.Join(", ", signature.Parameters.Select((type, index) => $"{WebAssemblyValueTypeToNative(type)} p{index}")));
                        Console.WriteLine(");");
                        continue;

                    case ExternalKind.Table:
                        // TODO
                        continue;

                    case ExternalKind.Memory:
                        // TODO
                        continue;

                    case ExternalKind.Global:
                        // TODO: Account for the indexes of imported globals--first internal global's index is 1 after the last imported.
                        var global = module.Globals[(int)export.Index];
                        Console.Write(indent);
                        Console.Write("public abstract ");
                        Console.Write(WebAssemblyValueTypeToNative(global.ContentType));
                        Console.Write(' ');
                        Console.Write(export.Name);
                        Console.Write(" { get;");
                        if (global.IsMutable)
                            Console.Write(" set;");
                        Console.WriteLine(" }");
                        continue;
                }
            }

on Wasm code it aim to global index 81:

(func $stackSave (;81;) (export "stackSave") (result i32)
    global.get $global0
  )

'Index was out of range" there is module.export that say is function index 81 but there are only 78 functions then throw error out of index i dont understand how to fix it

https://1drv.ms/u/s!AulOcG5BxeF6hqEWBbV0rMgcKlKLiw?e=iZeeYE

RyanLamansky commented 2 years ago

How many functions are imported?

bbday commented 2 years ago

there are 6 import functions. I put link before to download original wasm

RyanLamansky commented 2 years ago

Imports and internal functions get combined into the same index, so if you have 6 imports and 78 internals, the total is 84. 81 is past the 6 imports, so deduct 6 from 81 to get 75, which is the internal function being referenced in that example

bbday commented 2 years ago

I understand maybe i forgot to add import functions reference, is there some small example like import function that return current datetime?

should be like this:

 using var stream = File.OpenRead("module.wasm");
 var imports = new ImportDictionary
 {
   { "env", "time", new FunctionImport(new Func<long>(delegate() { return DateTimeOffset.Now.ToUnixTimeMilliseconds(); } )) },
 };
 var compiled = Compile.FromBinary<dynamic>(stream!)(imports);

If i try also without import anything i have error: "throw new StackTooSmallException(opcode, 1, stackCount);" (opcode = WebAssembly.OpCode.BranchIf , stackCount = 0)

Thanks.

RyanLamansky commented 2 years ago

The import code looks fine, but the StackToSmallException indicates a problem with the WASM file: it's trying to branch on nothing. There needs to be a 32-bit int on the stack where a non-zero value enters the branch and anything else does not.