Skip to content

Commit cf649b6

Browse files
committed
Merge 'main' and resolve conflicts.
2 parents e357e2c + b709269 commit cf649b6

12 files changed

+420
-376
lines changed

src/Function.FromCallback.cs

Lines changed: 130 additions & 130 deletions
Large diffs are not rendered by default.

src/Function.FromCallback.tt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ for (int hasCaller = 0; hasCaller < 2; hasCaller++)
155155
var parameterKinds = new List<ValueKind>();
156156
var resultKinds = new List<ValueKind>();
157157

158-
using var funcType = Function.GetFunctionType(callback.GetType(), parameterKinds, resultKinds, allowCaller: <#= (hasCaller > 0) ? "true" : "false" #>, allowTuple: <#= (resultCount > 1) ? "true" : "false" #>, out var hasCaller);
158+
using var funcType = Function.GetFunctionType(callback.GetType(), parameterKinds, resultKinds, allowCaller: <#= (hasCaller > 0) ? "true" : "false" #>, allowTuple: <#= (resultCount > 1) ? "true" : "false" #>, out _, out _);
159159

160160
<#= parameterConverters
161161
#>

src/Function.cs

Lines changed: 42 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,15 @@ public static Function FromCallback(IStore store, Delegate callback)
3535
var parameterKinds = new List<ValueKind>();
3636
var resultKinds = new List<ValueKind>();
3737

38-
using var funcType = GetFunctionType(callback.GetType(), parameterKinds, resultKinds, allowCaller: true, allowTuple: true, out var hasCaller);
38+
using var funcType = GetFunctionType(callback.GetType(), parameterKinds, resultKinds, allowCaller: true, allowTuple: true, out var hasCaller, out var returnsTuple);
39+
var callbackInvokeMethod = callback.GetType().GetMethod(nameof(Action.Invoke))!;
3940

4041
unsafe
4142
{
4243
Native.WasmtimeFuncCallback? func = (env, callerPtr, args, nargs, results, nresults) =>
4344
{
4445
using var caller = new Caller(callerPtr);
45-
return InvokeCallback(callback, caller, hasCaller, args, (int)nargs, results, (int)nresults, resultKinds);
46+
return InvokeCallback(callback, callbackInvokeMethod, caller, hasCaller, args, (int)nargs, results, (int)nresults, resultKinds, returnsTuple);
4647
};
4748

4849
Native.wasmtime_func_new(
@@ -1800,32 +1801,42 @@ private Function(IStore store, ExternFunc func, List<ValueKind> parameters, List
18001801
this.results = results;
18011802
}
18021803

1803-
private static IEnumerable<Type> EnumerateReturnTypes(Type? returnType)
1804+
private static IEnumerable<Type> EnumerateReturnTypes(Type? returnType, out bool isTuple)
18041805
{
1806+
isTuple = false;
1807+
18051808
if (returnType is null)
18061809
{
1807-
yield break;
1810+
return Array.Empty<Type>();
18081811
}
18091812

18101813
if (IsTuple(returnType))
18111814
{
1812-
foreach (var type in returnType
1813-
.GetGenericArguments()
1814-
.SelectMany(type =>
1815+
isTuple = true;
1816+
return EnumerateTupleTypes(returnType);
1817+
1818+
static IEnumerable<Type> EnumerateTupleTypes(Type tupleType)
1819+
{
1820+
foreach (var (typeArgument, idx) in tupleType.GenericTypeArguments.Select((e, idx) => (e, idx)))
1821+
{
1822+
if (idx is 7 && IsTuple(typeArgument))
18151823
{
1816-
if (type.IsConstructedGenericType)
1824+
// Recursively enumerate the nested tuple's type arguments.
1825+
foreach (var type in EnumerateTupleTypes(typeArgument))
18171826
{
1818-
return type.GenericTypeArguments;
1827+
yield return type;
18191828
}
1820-
return Enumerable.Repeat(type, 1);
1821-
}))
1822-
{
1823-
yield return type;
1829+
}
1830+
else
1831+
{
1832+
yield return typeArgument;
1833+
}
1834+
}
18241835
}
18251836
}
18261837
else
18271838
{
1828-
yield return returnType;
1839+
return new Type[] { returnType };
18291840
}
18301841
}
18311842

@@ -1849,7 +1860,7 @@ private static bool IsTuple(Type type)
18491860
definition == typeof(ValueTuple<,,,,,,,>);
18501861
}
18511862

1852-
internal static TypeHandle GetFunctionType(Type type, List<ValueKind> parameters, List<ValueKind> results, bool allowCaller, bool allowTuple, out bool hasCaller)
1863+
internal static TypeHandle GetFunctionType(Type type, List<ValueKind> parameters, List<ValueKind> results, bool allowCaller, bool allowTuple, out bool hasCaller, out bool returnsTuple)
18531864
{
18541865
if (!typeof(Delegate).IsAssignableFrom(type))
18551866
throw new ArgumentException("The specified type must be a Delegate type.");
@@ -1886,7 +1897,7 @@ internal static TypeHandle GetFunctionType(Type type, List<ValueKind> parameters
18861897
parameters.Add(kind);
18871898
}
18881899

1889-
results.AddRange(EnumerateReturnTypes(returnType).Select(t =>
1900+
results.AddRange(EnumerateReturnTypes(returnType, out returnsTuple).Select(t =>
18901901
{
18911902
if (!Value.TryGetKind(t, out var kind))
18921903
{
@@ -1895,16 +1906,15 @@ internal static TypeHandle GetFunctionType(Type type, List<ValueKind> parameters
18951906
return kind;
18961907
}));
18971908

1898-
// TODO: Once PR #161 is merged, uncomment this
1899-
//if (returnsTuple &&!allowTuple)
1900-
//{
1901-
// throw new ArgumentException("Use a different overload that implicitly returns ValueTuple.");
1902-
//}
1909+
if (returnsTuple && !allowTuple)
1910+
{
1911+
throw new ArgumentException("Use a different overload that implicitly returns ValueTuple.");
1912+
}
19031913

19041914
return new Function.TypeHandle(Function.Native.wasm_functype_new(new ValueTypeArray(parameters), new ValueTypeArray(results)));
19051915
}
19061916

1907-
internal unsafe static IntPtr InvokeCallback(Delegate callback, Caller caller, bool passCaller, Value* args, int nargs, Value* results, int nresults, IReadOnlyList<ValueKind> resultKinds)
1917+
internal unsafe static IntPtr InvokeCallback(Delegate callback, MethodInfo callbackInvokeMethod, Caller caller, bool passCaller, Value* args, int nargs, Value* results, int nresults, IReadOnlyList<ValueKind> resultKinds, bool returnsTuple)
19081918
{
19091919
try
19101920
{
@@ -1924,23 +1934,21 @@ internal unsafe static IntPtr InvokeCallback(Delegate callback, Caller caller, b
19241934

19251935
// NOTE: reflection is extremely slow for invoking methods. in the future, perhaps this could be replaced with
19261936
// source generators, system.linq.expressions, or generate IL with DynamicMethods or something
1927-
var result = callback.Method.Invoke(callback.Target, BindingFlags.DoNotWrapExceptions, null, invokeArgs, null);
1937+
var result = callbackInvokeMethod.Invoke(callback, BindingFlags.DoNotWrapExceptions, null, invokeArgs, null);
19281938

1929-
if (resultKinds.Count > 0)
1939+
if (returnsTuple)
19301940
{
1931-
var tuple = result as ITuple;
1932-
if (tuple is null)
1941+
var tuple = (ITuple)result!;
1942+
1943+
for (int i = 0; i < tuple.Length; ++i)
19331944
{
1934-
results[0] = Value.FromObject(result, resultKinds[0]);
1935-
}
1936-
else
1937-
{
1938-
for (int i = 0; i < tuple.Length; ++i)
1939-
{
1940-
results[i] = Value.FromObject(tuple[i], resultKinds[i]);
1941-
}
1945+
results[i] = Value.FromObject(tuple[i], resultKinds[i]);
19421946
}
19431947
}
1948+
else if (resultKinds.Count == 1)
1949+
{
1950+
results[0] = Value.FromObject(result, resultKinds[0]);
1951+
}
19441952
return IntPtr.Zero;
19451953
}
19461954
catch (Exception ex)

0 commit comments

Comments
 (0)