mirror of
https://github.com/Ryujinx/Opentk.git
synced 2025-03-29 18:06:52 +00:00
Merge branch 'arrayfix' into develop
This commit is contained in:
commit
50b611ec5f
|
@ -54,6 +54,7 @@ namespace OpenTK.Rewrite
|
||||||
static TypeDefinition TypeStringBuilder;
|
static TypeDefinition TypeStringBuilder;
|
||||||
static TypeDefinition TypeVoid;
|
static TypeDefinition TypeVoid;
|
||||||
static TypeDefinition TypeIntPtr;
|
static TypeDefinition TypeIntPtr;
|
||||||
|
static TypeDefinition TypeInt32;
|
||||||
|
|
||||||
// OpenTK.BindingsBase
|
// OpenTK.BindingsBase
|
||||||
static TypeDefinition TypeBindingsBase;
|
static TypeDefinition TypeBindingsBase;
|
||||||
|
@ -119,6 +120,7 @@ namespace OpenTK.Rewrite
|
||||||
TypeStringBuilder = mscorlib.MainModule.GetType("System.Text.StringBuilder");
|
TypeStringBuilder = mscorlib.MainModule.GetType("System.Text.StringBuilder");
|
||||||
TypeVoid = mscorlib.MainModule.GetType("System.Void");
|
TypeVoid = mscorlib.MainModule.GetType("System.Void");
|
||||||
TypeIntPtr = mscorlib.MainModule.GetType("System.IntPtr");
|
TypeIntPtr = mscorlib.MainModule.GetType("System.IntPtr");
|
||||||
|
TypeInt32 = mscorlib.MainModule.GetType("System.Int32");
|
||||||
|
|
||||||
TypeBindingsBase = assembly.Modules.Select(m => m.GetType("OpenTK.BindingsBase")).First();
|
TypeBindingsBase = assembly.Modules.Select(m => m.GetType("OpenTK.BindingsBase")).First();
|
||||||
|
|
||||||
|
@ -747,8 +749,28 @@ namespace OpenTK.Rewrite
|
||||||
{
|
{
|
||||||
if (p.Name != method.Module.Import(typeof(string[])).Name)
|
if (p.Name != method.Module.Import(typeof(string[])).Name)
|
||||||
{
|
{
|
||||||
|
// .Net treats 1d arrays differently than higher rank arrays.
|
||||||
|
// 1d arrays are directly supported by instructions such as ldlen and ldelema.
|
||||||
|
// Higher rank arrays must be accessed through System.Array methods such as get_Length.
|
||||||
|
// 1d array:
|
||||||
|
// check array is not null
|
||||||
|
// check ldlen array > 0
|
||||||
|
// ldc.i4.0
|
||||||
|
// ldelema
|
||||||
|
// 2d array:
|
||||||
|
// check array is not null
|
||||||
|
// check array.get_Length() > 0
|
||||||
|
// ldc.i4.0
|
||||||
|
// ldc.i4.0
|
||||||
|
// call instance T& T[0..., 0...]::Address(int32, int32)
|
||||||
|
// Mono treats everything as a 1d array.
|
||||||
|
// Interestingly, the .Net approach works on both Mono and .Net.
|
||||||
|
// The Mono approach fails when using high-rank arrays on .Net.
|
||||||
|
// We should report a bug to http://bugzilla.xamarin.com
|
||||||
|
|
||||||
// Pin the array and pass the address
|
// Pin the array and pass the address
|
||||||
// of its first element.
|
// of its first element.
|
||||||
|
var array = (ArrayType)p;
|
||||||
var element_type = p.GetElementType();
|
var element_type = p.GetElementType();
|
||||||
body.Variables.Add(new VariableDefinition(new PinnedType(new ByReferenceType(element_type))));
|
body.Variables.Add(new VariableDefinition(new PinnedType(new ByReferenceType(element_type))));
|
||||||
int pinned_index = body.Variables.Count - 1;
|
int pinned_index = body.Variables.Count - 1;
|
||||||
|
@ -756,14 +778,23 @@ namespace OpenTK.Rewrite
|
||||||
var empty = il.Create(OpCodes.Ldc_I4, 0);
|
var empty = il.Create(OpCodes.Ldc_I4, 0);
|
||||||
var pin = il.Create(OpCodes.Ldarg, i);
|
var pin = il.Create(OpCodes.Ldarg, i);
|
||||||
var end = il.Create(OpCodes.Stloc, pinned_index);
|
var end = il.Create(OpCodes.Stloc, pinned_index);
|
||||||
|
|
||||||
// if (array == null) goto empty
|
// if (array == null) goto empty
|
||||||
il.Emit(OpCodes.Brfalse, empty);
|
il.Emit(OpCodes.Brfalse, empty);
|
||||||
|
|
||||||
// else if (array.Length != 0) goto pin
|
// else if (array.Length != 0) goto pin
|
||||||
il.Emit(OpCodes.Ldarg, i);
|
il.Emit(OpCodes.Ldarg, i);
|
||||||
il.Emit(OpCodes.Ldlen);
|
if (array.Rank == 1)
|
||||||
il.Emit(OpCodes.Conv_I4);
|
{
|
||||||
|
il.Emit(OpCodes.Ldlen);
|
||||||
|
il.Emit(OpCodes.Conv_I4);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var get_length = method.Module.Import(
|
||||||
|
mscorlib.MainModule.GetType("System.Array").Methods.First(m => m.Name == "get_Length"));
|
||||||
|
il.Emit(OpCodes.Callvirt, get_length);
|
||||||
|
}
|
||||||
il.Emit(OpCodes.Brtrue, pin);
|
il.Emit(OpCodes.Brtrue, pin);
|
||||||
|
|
||||||
// empty: IntPtr ptr = IntPtr.Zero
|
// empty: IntPtr ptr = IntPtr.Zero
|
||||||
|
@ -773,8 +804,31 @@ namespace OpenTK.Rewrite
|
||||||
|
|
||||||
// pin: &array[0]
|
// pin: &array[0]
|
||||||
il.Append(pin);
|
il.Append(pin);
|
||||||
il.Emit(OpCodes.Ldc_I4, 0);
|
if (array.Rank == 1)
|
||||||
il.Emit(OpCodes.Ldelema, element_type);
|
{
|
||||||
|
// 1d array (vector), address is taken by ldelema
|
||||||
|
il.Emit(OpCodes.Ldc_I4, 0);
|
||||||
|
il.Emit(OpCodes.Ldelema, element_type);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 2d-3d array, address must be taken as follows:
|
||||||
|
// call instance T& T[0..., 0..., 0...]::Address(int, int, int)
|
||||||
|
ByReferenceType t_ref = array.ElementType.MakeByReferenceType();
|
||||||
|
MethodReference get_address = new MethodReference("Address", t_ref, array);
|
||||||
|
for (int r = 0; r < array.Rank; r++)
|
||||||
|
{
|
||||||
|
get_address.Parameters.Add(new ParameterDefinition(TypeInt32));
|
||||||
|
}
|
||||||
|
get_address.HasThis = true;
|
||||||
|
|
||||||
|
// emit the get_address call
|
||||||
|
for (int r = 0; r < array.Rank; r++)
|
||||||
|
{
|
||||||
|
il.Emit(OpCodes.Ldc_I4, 0);
|
||||||
|
}
|
||||||
|
il.Emit(OpCodes.Call, get_address);
|
||||||
|
}
|
||||||
|
|
||||||
// end: fixed (IntPtr ptr = &array[0])
|
// end: fixed (IntPtr ptr = &array[0])
|
||||||
il.Append(end);
|
il.Append(end);
|
||||||
|
|
Loading…
Reference in a new issue