示例#1
0
    static string GenPinvokeDecl(Pinvoke pinvoke)
    {
        var sb     = new StringBuilder();
        var method = pinvoke.Method;

        sb.Append(WasmTuner.MapType(method.ReturnType));
        sb.Append($" {pinvoke.EntryPoint} (");
        int pindex = 0;

        foreach (var p in method.Parameters)
        {
            if (pindex > 0)
            {
                sb.Append(",");
            }
            sb.Append(WasmTuner.MapType(method.Parameters [pindex].ParameterType));
            pindex++;
        }
        sb.Append(");");
        return(sb.ToString());
    }
示例#2
0
    void GenNativeToInterp()
    {
        // Generate native->interp entry functions
        // These are called by native code, so they need to obtain
        // the interp entry function/arg from a global array
        // They also need to have a signature matching what the
        // native code expects, which is the native signature
        // of the delegate invoke in the [MonoPInvokeCallback]
        // attribute.
        // Only blittable parameter/return types are supposed.
        int cb_index = 0;

        // Arguments to interp entry functions in the runtime
        Console.WriteLine("InterpFtnDesc wasm_native_to_interp_ftndescs[" + callbacks.Count + "];");

        foreach (var cb in callbacks)
        {
            var method = cb.Method;

            if (!IsBlittable(method.ReturnType))
            {
                Error("The return type of pinvoke callback method '" + method.FullName + "' needs to be blittable.");
            }
            foreach (var p in method.Parameters)
            {
                if (!IsBlittable(p.ParameterType))
                {
                    Error("Parameter types of pinvoke callback method '" + method.FullName + "' needs to be blittable.");
                }
            }
        }

        foreach (var cb in callbacks)
        {
            var sb     = new StringBuilder();
            var method = cb.Method;

            // The signature of the interp entry function
            // This is a gsharedvt_in signature
            sb.Append("typedef void ");
            sb.Append(" (*WasmInterpEntrySig_" + cb_index + ") (");
            int pindex = 0;
            if (method.ReturnType.Name != "Void")
            {
                sb.Append("int");
                pindex++;
            }
            foreach (var p in method.Parameters)
            {
                if (pindex > 0)
                {
                    sb.Append(",");
                }
                sb.Append("int");
                pindex++;
            }
            if (pindex > 0)
            {
                sb.Append(",");
            }
            // Extra arg
            sb.Append("int");
            sb.Append(");\n");

            bool is_void = method.ReturnType.Name == "Void";

            string module_symbol = method.DeclaringType.Module.Assembly.Name.Name.Replace(".", "_");
            var    token         = method.MetadataToken.ToUInt32();
            string entry_name    = $"wasm_native_to_interp_{module_symbol}_{token}";
            cb.EntryName = entry_name;
            sb.Append(WasmTuner.MapType(method.ReturnType));
            sb.Append($" {entry_name} (");
            pindex = 0;
            foreach (var p in method.Parameters)
            {
                if (pindex > 0)
                {
                    sb.Append(",");
                }
                sb.Append(WasmTuner.MapType(method.Parameters [pindex].ParameterType));
                sb.Append(" arg" + pindex);
                pindex++;
            }
            sb.Append(") { \n");
            if (!is_void)
            {
                sb.Append(WasmTuner.MapType(method.ReturnType) + " res;\n");
            }
            sb.Append("((WasmInterpEntrySig_" + cb_index + ")wasm_native_to_interp_ftndescs [" + cb_index + "].func) (");
            pindex = 0;
            if (!is_void)
            {
                sb.Append("&res");
                pindex++;
            }
            int aindex = 0;
            foreach (var p in method.Parameters)
            {
                if (pindex > 0)
                {
                    sb.Append(", ");
                }
                sb.Append("&arg" + aindex);
                pindex++;
                aindex++;
            }
            if (pindex > 0)
            {
                sb.Append(", ");
            }
            sb.Append($"wasm_native_to_interp_ftndescs [{cb_index}].arg");
            sb.Append(");\n");
            if (!is_void)
            {
                sb.Append("return res;\n");
            }
            sb.Append("}");
            Console.WriteLine(sb);
            cb_index++;
        }

        // Array of function pointers
        Console.Write("static void *wasm_native_to_interp_funcs[] = { ");
        foreach (var cb in callbacks)
        {
            Console.Write(cb.EntryName + ",");
        }
        Console.WriteLine("};");

        // Lookup table from method->interp entry
        // The key is a string of the form <assembly name>_<method token>
        // FIXME: Use a better encoding
        Console.Write("static const char *wasm_native_to_interp_map[] = { ");
        foreach (var cb in callbacks)
        {
            var    method        = cb.Method;
            string module_symbol = method.DeclaringType.Module.Assembly.Name.Name.Replace(".", "_");
            var    token         = method.MetadataToken.ToUInt32();
            Console.WriteLine($"\"{module_symbol}_{token}\",");
        }
        Console.WriteLine("};");
    }