return sb.ToString();
}
- void EmitNativeToInterp(StreamWriter w, List<PInvokeCallback> callbacks)
+ void EmitNativeToInterp(StreamWriter w, List<PInvokeCallback> callbacks)
{
- // 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
- w.WriteLine("InterpFtnDesc wasm_native_to_interp_ftndescs[" + callbacks.Count + "];");
-
- foreach (var cb in callbacks) {
- var method = cb.Method;
-
- if (method.ReturnType != typeof(void) && !IsBlittable(method.ReturnType))
- Error("The return type of pinvoke callback method '" + method + "' needs to be blittable.");
- foreach (var p in method.GetParameters()) {
- if (!IsBlittable(p.ParameterType))
- Error("Parameter types of pinvoke callback method '" + method + "' 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.GetParameters()) {
- 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!.GetName()!.Name!.Replace(".", "_");
- uint token = (uint)method.MetadataToken;
- string entry_name = $"wasm_native_to_interp_{module_symbol}_{token}";
+ // 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
+ w.WriteLine("InterpFtnDesc wasm_native_to_interp_ftndescs[" + callbacks.Count + "];");
+
+ foreach (var cb in callbacks) {
+ var method = cb.Method;
+
+ if (method.ReturnType != typeof(void) && !IsBlittable(method.ReturnType))
+ Error("The return type of pinvoke callback method '" + method + "' needs to be blittable.");
+ foreach (var p in method.GetParameters()) {
+ if (!IsBlittable(p.ParameterType))
+ Error("Parameter types of pinvoke callback method '" + method + "' needs to be blittable.");
+ }
+ }
+
+ var callbackNames = new HashSet<string>();
+
+ 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.GetParameters()) {
+ 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!.GetName()!.Name!.Replace(".", "_");
+ uint token = (uint)method.MetadataToken;
+ string class_name = method.DeclaringType.Name;
+ string method_name = method.Name;
+ string entry_name = $"wasm_native_to_interp_{module_symbol}_{class_name}_{method_name}";
+ if (callbackNames.Contains (entry_name))
+ {
+ Error($"Two callbacks with the same name '{method_name}' are not supported.");
+ }
+ callbackNames.Add (entry_name);
cb.EntryName = entry_name;
- sb.Append(MapType(method.ReturnType));
- sb.Append($" {entry_name} (");
- pindex = 0;
- foreach (var p in method.GetParameters()) {
- if (pindex > 0)
- sb.Append(",");
- sb.Append(MapType(method.GetParameters()[pindex].ParameterType));
- sb.Append(" arg" + pindex);
- pindex ++;
- }
- sb.Append(") { \n");
- if (!is_void)
- sb.Append(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.GetParameters()) {
- 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("}");
- w.WriteLine(sb);
- cb_index ++;
- }
-
- // Array of function pointers
- w.Write ("static void *wasm_native_to_interp_funcs[] = { ");
- foreach (var cb in callbacks) {
- w.Write (cb.EntryName + ",");
- }
- w.WriteLine ("};");
-
- // Lookup table from method->interp entry
- // The key is a string of the form <assembly name>_<method token>
- // FIXME: Use a better encoding
- w.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!.GetName()!.Name!.Replace(".", "_");
- uint token = (uint)method.MetadataToken;
- w.WriteLine ($"\"{module_symbol}_{token}\",");
- }
- w.WriteLine ("};");
- }
+ sb.Append(MapType(method.ReturnType));
+ sb.Append($" {entry_name} (");
+ pindex = 0;
+ foreach (var p in method.GetParameters()) {
+ if (pindex > 0)
+ sb.Append(",");
+ sb.Append(MapType(method.GetParameters()[pindex].ParameterType));
+ sb.Append(" arg" + pindex);
+ pindex ++;
+ }
+ sb.Append(") { \n");
+ if (!is_void)
+ sb.Append(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.GetParameters()) {
+ 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("}");
+ w.WriteLine(sb);
+ cb_index ++;
+ }
+
+ // Array of function pointers
+ w.Write ("static void *wasm_native_to_interp_funcs[] = { ");
+ foreach (var cb in callbacks) {
+ w.Write (cb.EntryName + ",");
+ }
+ w.WriteLine ("};");
+
+ // Lookup table from method->interp entry
+ // The key is a string of the form <assembly name>_<method token>
+ // FIXME: Use a better encoding
+ w.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!.GetName()!.Name!.Replace(".", "_");
+ string class_name = method.DeclaringType.Name;
+ string method_name = method.Name;
+ w.WriteLine ($"\"{module_symbol}_{class_name}_{method_name}\",");
+ }
+ w.WriteLine ("};");
+ }
static bool IsBlittable (Type type)
{