mirror of
https://github.com/Ryujinx/Opentk.git
synced 2025-01-23 12:21:02 +00:00
Corrected the handling of arrays
This includes arrays of primitives and arrays of generics. Our code is similar to the code generated by the Mono C# compiler for the "fixed" construct. The .Net compiler produces slightly different code (two local variables instead of one) - more research is required.
This commit is contained in:
parent
0d9df5ad72
commit
31d14cebff
|
@ -350,16 +350,57 @@ namespace OpenTK.Rewrite
|
||||||
var p = method.Parameters[i];
|
var p = method.Parameters[i];
|
||||||
il.Emit(OpCodes.Ldarg, i);
|
il.Emit(OpCodes.Ldarg, i);
|
||||||
|
|
||||||
if (p.ParameterType.IsGenericInstance)
|
if (p.ParameterType.IsByReference)
|
||||||
{
|
{
|
||||||
|
body.Variables.Add(new VariableDefinition(new PinnedType(p.ParameterType)));
|
||||||
}
|
|
||||||
else if (p.ParameterType.IsArray || p.ParameterType.IsByReference)
|
|
||||||
{
|
|
||||||
body.Variables.Add(new VariableDefinition(new PinnedType(nint)));
|
|
||||||
var index = body.Variables.Count - 1;
|
var index = body.Variables.Count - 1;
|
||||||
il.Emit(OpCodes.Stloc, index);
|
il.Emit(OpCodes.Stloc, index);
|
||||||
il.Emit(OpCodes.Ldloc, index);
|
il.Emit(OpCodes.Ldloc, index);
|
||||||
|
il.Emit(OpCodes.Conv_I);
|
||||||
|
}
|
||||||
|
else if (p.ParameterType.IsArray)
|
||||||
|
{
|
||||||
|
if (p.ParameterType.Name != method.Module.Import(typeof(string[])).Name)
|
||||||
|
{
|
||||||
|
// Pin the array and pass the address
|
||||||
|
// of its first element.
|
||||||
|
var element_type = p.ParameterType.GetElementType();
|
||||||
|
body.Variables.Add(new VariableDefinition(new PinnedType(new ByReferenceType(element_type))));
|
||||||
|
int pinned_index = body.Variables.Count - 1;
|
||||||
|
|
||||||
|
var empty = il.Create(OpCodes.Ldc_I4, 0);
|
||||||
|
var pin = il.Create(OpCodes.Ldarg, i);
|
||||||
|
var end = il.Create(OpCodes.Stloc, pinned_index);
|
||||||
|
|
||||||
|
// if (array == null) goto empty
|
||||||
|
il.Emit(OpCodes.Brfalse, empty);
|
||||||
|
|
||||||
|
// else if (array.Length != 0) goto pin
|
||||||
|
il.Emit(OpCodes.Ldarg, i);
|
||||||
|
il.Emit(OpCodes.Ldlen);
|
||||||
|
il.Emit(OpCodes.Conv_I4);
|
||||||
|
il.Emit(OpCodes.Brtrue, pin);
|
||||||
|
|
||||||
|
// empty: IntPtr ptr = IntPtr.Zero
|
||||||
|
il.Append(empty);
|
||||||
|
il.Emit(OpCodes.Conv_U);
|
||||||
|
il.Emit(OpCodes.Br, end);
|
||||||
|
|
||||||
|
// pin: &array[0]
|
||||||
|
il.Append(pin);
|
||||||
|
il.Emit(OpCodes.Ldc_I4, 0);
|
||||||
|
il.Emit(OpCodes.Ldelema, element_type);
|
||||||
|
|
||||||
|
// end: fixed (IntPtr ptr = &array[0])
|
||||||
|
il.Append(end);
|
||||||
|
il.Emit(OpCodes.Ldloc, pinned_index);
|
||||||
|
il.Emit(OpCodes.Conv_I);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// String[] requires special marshalling.
|
||||||
|
// Let the runtime handle this for now.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
|
|
Loading…
Reference in a new issue