mirror of
https://github.com/Ryujinx/Opentk.git
synced 2025-03-26 10:25:14 +00:00
Clean up wrapper generation
We can now apply multiple WrapperTypes values to a single parameter.
This commit is contained in:
parent
e178f306eb
commit
4286b47d6f
|
@ -400,9 +400,9 @@ namespace Bind
|
|||
|
||||
// If we have a convenience overload, we should turn the name from
|
||||
// plural into singular
|
||||
if (d.ReturnType.WrapperType == WrapperTypes.ConvenienceReturnType ||
|
||||
d.ReturnType.WrapperType == WrapperTypes.ConvenienceArrayReturnType ||
|
||||
d.Parameters.Any(p => p.WrapperType == WrapperTypes.ConvenienceArrayType))
|
||||
if ((d.ReturnType.WrapperType & WrapperTypes.ConvenienceReturnType) != 0 ||
|
||||
(d.ReturnType.WrapperType & WrapperTypes.ConvenienceArrayReturnType) != 0 ||
|
||||
d.Parameters.Any(p => (p.WrapperType & WrapperTypes.ConvenienceArrayType) != 0))
|
||||
{
|
||||
trimmed_name = trimmed_name.Replace("Queries", "Query");
|
||||
trimmed_name = trimmed_name.TrimEnd('s');
|
||||
|
@ -529,17 +529,17 @@ namespace Bind
|
|||
|
||||
TranslateType(d.ReturnType, function_override, nav, enum_processor,enums, d.Category, apiname);
|
||||
|
||||
if (d.ReturnType.CurrentType.ToLower().Contains("void") && d.ReturnType.Pointer != 0)
|
||||
if (d.ReturnType.CurrentType.ToLower() == "void" && d.ReturnType.Pointer != 0)
|
||||
{
|
||||
d.ReturnType.QualifiedType = "IntPtr";
|
||||
d.ReturnType.Pointer--;
|
||||
d.ReturnType.WrapperType = WrapperTypes.GenericReturnType;
|
||||
d.ReturnType.WrapperType |= WrapperTypes.GenericReturnType;
|
||||
}
|
||||
|
||||
if (d.ReturnType.CurrentType.ToLower().Contains("string"))
|
||||
if (d.ReturnType.CurrentType.ToLower() == "string")
|
||||
{
|
||||
d.ReturnType.QualifiedType = "IntPtr";
|
||||
d.ReturnType.WrapperType = WrapperTypes.StringReturnType;
|
||||
d.ReturnType.WrapperType |= WrapperTypes.StringReturnType;
|
||||
}
|
||||
|
||||
if (d.ReturnType.CurrentType.ToLower() == "object")
|
||||
|
@ -585,7 +585,7 @@ namespace Bind
|
|||
{
|
||||
TranslateParameter(d.Parameters[i], function_override, nav, enum_processor, enums, d.Category, apiname);
|
||||
if (d.Parameters[i].CurrentType == "UInt16" && d.Name.Contains("LineStipple"))
|
||||
d.Parameters[i].WrapperType = WrapperTypes.UncheckedParameter;
|
||||
d.Parameters[i].WrapperType |= WrapperTypes.UncheckedParameter;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -596,48 +596,71 @@ namespace Bind
|
|||
{
|
||||
TranslateType(p, function_override, overrides, enum_processor, enums, category, apiname);
|
||||
|
||||
// Find out the necessary wrapper types.
|
||||
if (p.Pointer != 0)/* || CurrentType == "IntPtr")*/
|
||||
// Translate char* -> string. This simplifies the rest of the logic below
|
||||
if (p.CurrentType.ToLower().Contains("char") && p.Pointer > 0)
|
||||
{
|
||||
if (p.CurrentType.ToLower().Contains("string") ||
|
||||
p.CurrentType.ToLower().Contains("char") && p.Pointer > 1)
|
||||
{
|
||||
// string* -> [In] String[] or [Out] StringBuilder[]
|
||||
p.QualifiedType =
|
||||
p.Flow == FlowDirection.Out ?
|
||||
"StringBuilder[]" :
|
||||
"String[]";
|
||||
p.CurrentType = "string";
|
||||
p.Pointer--;
|
||||
}
|
||||
|
||||
p.Pointer = 0;
|
||||
p.WrapperType = WrapperTypes.None;
|
||||
}
|
||||
else if (p.CurrentType.ToLower().Contains("char"))
|
||||
// Find out the necessary wrapper types.
|
||||
if (p.CurrentType.ToLower() == "string" && p.Pointer == 0)
|
||||
{
|
||||
// char* -> [In] String or [Out] StringBuilder
|
||||
if (p.Flow == FlowDirection.Out)
|
||||
{
|
||||
// char* -> [In] String or [Out] StringBuilder
|
||||
p.QualifiedType =
|
||||
p.Flow == FlowDirection.Out ?
|
||||
"StringBuilder" :
|
||||
"String";
|
||||
|
||||
p.Pointer = 0;
|
||||
p.WrapperType = WrapperTypes.None;
|
||||
}
|
||||
else if (p.CurrentType.ToLower().Contains("void") ||
|
||||
(!String.IsNullOrEmpty(p.PreviousType) && p.PreviousType.ToLower().Contains("void")))
|
||||
//|| CurrentType.Contains("IntPtr"))
|
||||
{
|
||||
p.CurrentType = "IntPtr";
|
||||
p.Pointer = 0;
|
||||
p.WrapperType = WrapperTypes.GenericParameter;
|
||||
// Due to a bug in the Mono runtime, we need
|
||||
// to marshal out string parameters ourselves.
|
||||
// StringBuilder crashes at runtime.
|
||||
p.QualifiedType = "IntPtr";
|
||||
}
|
||||
else
|
||||
{
|
||||
p.WrapperType = WrapperTypes.ArrayParameter;
|
||||
// in string parameters work fine on both
|
||||
// Mono and .Net.
|
||||
p.QualifiedType = "String";
|
||||
}
|
||||
|
||||
p.WrapperType |= WrapperTypes.StringParameter;
|
||||
}
|
||||
|
||||
if (p.Reference)
|
||||
p.WrapperType |= WrapperTypes.ReferenceParameter;
|
||||
if (p.CurrentType.ToLower() == "string" && p.Pointer >= 1)
|
||||
{
|
||||
// string* -> [In] String[]
|
||||
// [Out] StringBuilder[] parameter is not currently supported
|
||||
// Higher indirection levels are also not supported
|
||||
if (p.Flow == FlowDirection.Out)
|
||||
{
|
||||
throw new NotSupportedException("[Out] String* parameters are not currently supported.");
|
||||
}
|
||||
if (p.Pointer >= 2)
|
||||
{
|
||||
throw new NotSupportedException("String arrays with arity >= 2 are not currently supported.");
|
||||
}
|
||||
|
||||
p.QualifiedType = "String";
|
||||
p.Pointer = 0;
|
||||
p.Array = 1;
|
||||
p.WrapperType |= WrapperTypes.StringArrayParameter;
|
||||
}
|
||||
|
||||
if (p.Pointer > 0 && p.WrapperType == 0)
|
||||
{
|
||||
if (p.QualifiedType.ToLower().StartsWith("void"))
|
||||
{
|
||||
p.QualifiedType = "IntPtr";
|
||||
p.Pointer = 0; // Generic parameters cannot have pointers
|
||||
p.WrapperType |= WrapperTypes.GenericParameter;
|
||||
p.WrapperType |= WrapperTypes.ArrayParameter;
|
||||
p.WrapperType |= WrapperTypes.ReferenceParameter;
|
||||
}
|
||||
else
|
||||
{
|
||||
p.WrapperType |= WrapperTypes.ArrayParameter;
|
||||
p.WrapperType |= WrapperTypes.ReferenceParameter;
|
||||
p.WrapperType |= WrapperTypes.PointerParameter;
|
||||
}
|
||||
}
|
||||
|
||||
if (Utilities.Keywords(Settings.Language).Contains(p.Name))
|
||||
p.Name = Settings.KeywordEscapeCharacter + p.Name;
|
||||
|
@ -910,7 +933,7 @@ namespace Bind
|
|||
f.ReturnType = new Type(f.Parameters.Last());
|
||||
f.ReturnType.Pointer = 0;
|
||||
f.Parameters.RemoveAt(f.Parameters.Count - 1);
|
||||
f.ReturnType.WrapperType = WrapperTypes.ConvenienceReturnType;
|
||||
f.ReturnType.WrapperType |= WrapperTypes.ConvenienceReturnType;
|
||||
|
||||
if (f.Parameters.Count > 0)
|
||||
{
|
||||
|
@ -918,7 +941,7 @@ namespace Bind
|
|||
if (p_size.CurrentType.ToLower().StartsWith("int") && p_size.Pointer == 0)
|
||||
{
|
||||
f.Parameters.RemoveAt(f.Parameters.Count - 1);
|
||||
f.ReturnType.WrapperType = WrapperTypes.ConvenienceArrayReturnType;
|
||||
f.ReturnType.WrapperType |= WrapperTypes.ConvenienceArrayReturnType;
|
||||
}
|
||||
}
|
||||
return f;
|
||||
|
@ -930,172 +953,228 @@ namespace Bind
|
|||
var p_array = f.Parameters.Last();
|
||||
var p_size = f.Parameters[f.Parameters.Count - 2];
|
||||
f.Parameters.RemoveAt(f.Parameters.Count - 2);
|
||||
p_array.WrapperType = WrapperTypes.ConvenienceArrayType;
|
||||
p_array.Pointer = 0;
|
||||
p_array.WrapperType |= WrapperTypes.ConvenienceArrayType;
|
||||
// Since this is a 1-element overload, we don't need
|
||||
// array or reference wrappers.
|
||||
p_array.WrapperType &= ~(
|
||||
WrapperTypes.ReferenceParameter |
|
||||
WrapperTypes.ArrayParameter);
|
||||
p_array.Array = p_array.Pointer = 0;
|
||||
p_array.Reference = false;
|
||||
return f;
|
||||
}
|
||||
|
||||
List<Function> GetWrapper(IDictionary<WrapperTypes, List<Function>> dictionary, WrapperTypes key, Function raw)
|
||||
{
|
||||
if (!dictionary.ContainsKey(key))
|
||||
{
|
||||
dictionary.Add(key, new List<Function>());
|
||||
if (raw != null)
|
||||
{
|
||||
dictionary[key].Add(new Function(raw));
|
||||
}
|
||||
}
|
||||
return dictionary[key];
|
||||
}
|
||||
|
||||
public IEnumerable<Function> WrapParameters(Function func, EnumCollection enums)
|
||||
{
|
||||
Function f;
|
||||
|
||||
if (func.Parameters.HasPointerParameters)
|
||||
if (func.Parameters.Count == 0)
|
||||
{
|
||||
Function _this = new Function(func);
|
||||
// Array overloads
|
||||
foreach (Parameter p in _this.Parameters)
|
||||
// Functions without parameters do not need
|
||||
// parameter wrappers
|
||||
yield return func;
|
||||
yield break;
|
||||
}
|
||||
|
||||
var wrappers = new Dictionary<WrapperTypes, List<Function>>();
|
||||
for (int i = 0; i < func.Parameters.Count; i++)
|
||||
{
|
||||
var parameter = func.Parameters[i];
|
||||
|
||||
// Handle all non-generic parameters first.
|
||||
// Generics are handled in a second pass.
|
||||
if ((parameter.WrapperType & WrapperTypes.GenericParameter) == 0)
|
||||
{
|
||||
if (p.WrapperType == WrapperTypes.ArrayParameter)
|
||||
if ((parameter.WrapperType & WrapperTypes.ArrayParameter) != 0)
|
||||
{
|
||||
if (p.ElementCount != 1)
|
||||
foreach (var wrapper in GetWrapper(wrappers, WrapperTypes.ArrayParameter, func))
|
||||
{
|
||||
// Create a proper array
|
||||
p.Reference = false;
|
||||
p.Array++;
|
||||
var p = wrapper.Parameters[i];
|
||||
|
||||
if (p.ElementCount == 1)
|
||||
{
|
||||
p.Reference = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
p.Array++;
|
||||
}
|
||||
p.Pointer--;
|
||||
}
|
||||
}
|
||||
|
||||
if ((parameter.WrapperType & WrapperTypes.ReferenceParameter) != 0)
|
||||
{
|
||||
foreach (var wrapper in GetWrapper(wrappers, WrapperTypes.ReferenceParameter, func))
|
||||
{
|
||||
var p = wrapper.Parameters[i];
|
||||
|
||||
p.Reference = true;
|
||||
p.Pointer--;
|
||||
}
|
||||
}
|
||||
|
||||
if ((parameter.WrapperType & WrapperTypes.PointerParameter) != 0)
|
||||
{
|
||||
foreach (var wrapper in GetWrapper(wrappers, WrapperTypes.PointerParameter, func))
|
||||
{
|
||||
var p = wrapper.Parameters[i];
|
||||
|
||||
if (Settings.IsEnabled(Settings.Legacy.NoPublicUnsafeFunctions))
|
||||
{
|
||||
p.QualifiedType = "IntPtr";
|
||||
p.Pointer = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (parameter.WrapperType == 0 ||
|
||||
(parameter.WrapperType & WrapperTypes.ConvenienceArrayType) != 0 ||
|
||||
(parameter.WrapperType & WrapperTypes.ConvenienceReturnType) != 0 ||
|
||||
(parameter.WrapperType & WrapperTypes.ConvenienceArrayReturnType) != 0)
|
||||
{
|
||||
// We don't need to do anything, just add this function directly
|
||||
// to the list of wrappers.
|
||||
GetWrapper(wrappers, parameter.WrapperType, func);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle generic parameters
|
||||
if (wrappers.Count == 0)
|
||||
{
|
||||
// Some functions, such as VDPAUInit, only have generic parameters
|
||||
// This means no wrapper has been generated by any of the previous
|
||||
// transformations. Since the generic translation below operates on
|
||||
// existing wrappers, add one here to get the process started.
|
||||
wrappers.Add(WrapperTypes.None, new List<Function> { new Function(func) });
|
||||
}
|
||||
var list = new List<Function>();
|
||||
foreach (var wrapper in wrappers.Values.SelectMany(v => v))
|
||||
{
|
||||
// Add generic 'ref T' wrapper
|
||||
Function generic_wrapper = null;
|
||||
for (int i = 0; i < wrapper.Parameters.Count; i++)
|
||||
{
|
||||
var parameter = wrapper.Parameters[i];
|
||||
if ((parameter.WrapperType & WrapperTypes.GenericParameter) != 0)
|
||||
{
|
||||
generic_wrapper = generic_wrapper ?? new Function(wrapper);
|
||||
var p = generic_wrapper.Parameters[i];
|
||||
|
||||
p.Reference = true;
|
||||
p.Pointer = 0;
|
||||
p.Array = 0;
|
||||
p.Generic = true;
|
||||
p.QualifiedType = "T" + i.ToString();
|
||||
p.Flow = FlowDirection.Undefined;
|
||||
}
|
||||
}
|
||||
if (generic_wrapper != null)
|
||||
{
|
||||
list.Add(generic_wrapper);
|
||||
}
|
||||
|
||||
// Add the following wrappers:
|
||||
// 'IntPtr', 'T[]', 'T[,]' and 'T[,,]'
|
||||
for (int arity = 0; arity < 4; arity++)
|
||||
{
|
||||
generic_wrapper = null;
|
||||
for (int i = 0; i < wrapper.Parameters.Count; i++)
|
||||
{
|
||||
var parameter = wrapper.Parameters[i];
|
||||
if ((parameter.WrapperType & WrapperTypes.GenericParameter) != 0)
|
||||
{
|
||||
generic_wrapper = generic_wrapper ?? new Function(wrapper);
|
||||
var p = generic_wrapper.Parameters[i];
|
||||
|
||||
p.Reference = false;
|
||||
p.Pointer = 0;
|
||||
p.Array = arity;
|
||||
if (arity == 0)
|
||||
{
|
||||
p.QualifiedType = "IntPtr";
|
||||
}
|
||||
else
|
||||
{
|
||||
p.Generic = true;
|
||||
p.QualifiedType = "T" + i.ToString();
|
||||
p.Flow = FlowDirection.Undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (generic_wrapper != null)
|
||||
{
|
||||
list.Add(generic_wrapper);
|
||||
}
|
||||
}
|
||||
}
|
||||
GetWrapper(wrappers, WrapperTypes.GenericParameter, null)
|
||||
.AddRange(list);
|
||||
|
||||
// Handle string parameters
|
||||
foreach (var wrapper in wrappers.Values.SelectMany(v => v))
|
||||
{
|
||||
for (int i = 0; i < wrapper.Parameters.Count; i++)
|
||||
{
|
||||
var p = wrapper.Parameters[i];
|
||||
if ((p.WrapperType & WrapperTypes.StringParameter) != 0)
|
||||
{
|
||||
if (p.Flow == FlowDirection.Out)
|
||||
{
|
||||
p.QualifiedType = "StringBuilder";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create a reference
|
||||
p.Reference = true;
|
||||
p.Array--;
|
||||
p.Pointer--;
|
||||
p.WrapperType = WrapperTypes.ReferenceParameter;
|
||||
p.QualifiedType = "String";
|
||||
}
|
||||
}
|
||||
|
||||
if ((p.WrapperType & WrapperTypes.StringArrayParameter) != 0)
|
||||
{
|
||||
if (p.Flow == FlowDirection.Out)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
else
|
||||
{
|
||||
p.QualifiedType = "String";
|
||||
p.Pointer = 0;
|
||||
p.Array = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
f = new Function(_this);
|
||||
yield return f;
|
||||
foreach (var w in WrapVoidPointers(f, enums))
|
||||
yield return w;
|
||||
|
||||
_this = new Function(func);
|
||||
// Reference overloads
|
||||
foreach (Parameter p in _this.Parameters)
|
||||
{
|
||||
if (p.WrapperType == WrapperTypes.ArrayParameter)
|
||||
{
|
||||
p.Reference = true;
|
||||
p.Array--;
|
||||
p.Pointer--;
|
||||
p.WrapperType = WrapperTypes.ReferenceParameter;
|
||||
}
|
||||
}
|
||||
f = new Function(_this);
|
||||
yield return f;
|
||||
foreach (var w in WrapVoidPointers(f, enums))
|
||||
yield return w;
|
||||
|
||||
_this = func;
|
||||
// Pointer overloads
|
||||
// Should be last to work around an Intellisense bug, where
|
||||
// array overloads are not reported if there is a pointer overload.
|
||||
foreach (Parameter p in _this.Parameters)
|
||||
{
|
||||
if (p.WrapperType == WrapperTypes.ArrayParameter)
|
||||
{
|
||||
p.Reference = false;
|
||||
p.WrapperType = WrapperTypes.PointerParameter;
|
||||
}
|
||||
}
|
||||
f = new Function(_this);
|
||||
yield return f;
|
||||
foreach (var w in WrapVoidPointers(f, enums))
|
||||
yield return w;
|
||||
}
|
||||
else
|
||||
|
||||
// Return all generated wrappers
|
||||
foreach (var w in wrappers.Values.SelectMany(v => v).OrderBy(v => v))
|
||||
{
|
||||
f = new Function(func);
|
||||
yield return f;
|
||||
yield return w;
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerable<Function> WrapVoidPointers(Function f, EnumCollection enums)
|
||||
{
|
||||
// reference wrapper (e.g. void Foo<T1,T2>(int, ref T1, ref T2))
|
||||
var func = new Function(f);
|
||||
int index = -1;
|
||||
foreach (var p in func.Parameters)
|
||||
{
|
||||
index++;
|
||||
if (p.WrapperType == WrapperTypes.GenericParameter)
|
||||
{
|
||||
p.Reference = true;
|
||||
p.Array = 0;
|
||||
p.Pointer = 0;
|
||||
p.Generic = true;
|
||||
p.CurrentType = "T" + index.ToString();
|
||||
p.Flow = FlowDirection.Undefined;
|
||||
func.Parameters.Rebuild = true;
|
||||
}
|
||||
}
|
||||
yield return func;
|
||||
|
||||
// 1d-array wrapper (e.g. void Foo<T1, T2>(int, T1[], T2[]))
|
||||
func = new Function(f);
|
||||
index = -1;
|
||||
foreach (var p in func.Parameters)
|
||||
{
|
||||
index++;
|
||||
if (p.WrapperType == WrapperTypes.GenericParameter)
|
||||
{
|
||||
p.Reference = false;
|
||||
p.Array = 1;
|
||||
p.Pointer = 0;
|
||||
p.Generic = true;
|
||||
p.CurrentType = "T" + index.ToString();
|
||||
p.Flow = FlowDirection.Undefined;
|
||||
func.Parameters.Rebuild = true;
|
||||
}
|
||||
}
|
||||
yield return func;
|
||||
|
||||
// 2d-array wrapper (e.g. void Foo<T1, T2>(int, T1[,], T2[,]))
|
||||
func = new Function(f);
|
||||
index = -1;
|
||||
foreach (var p in func.Parameters)
|
||||
{
|
||||
index++;
|
||||
if (p.WrapperType == WrapperTypes.GenericParameter)
|
||||
{
|
||||
p.Reference = false;
|
||||
p.Array = 2;
|
||||
p.Pointer = 0;
|
||||
p.Generic = true;
|
||||
p.CurrentType = "T" + index.ToString();
|
||||
p.Flow = FlowDirection.Undefined;
|
||||
func.Parameters.Rebuild = true;
|
||||
}
|
||||
}
|
||||
yield return func;
|
||||
|
||||
// 3d-array wrapper (e.g. void Foo<T1, T2>(int, T1[,,], T2[,,]))
|
||||
func = new Function(f);
|
||||
index = -1;
|
||||
foreach (var p in func.Parameters)
|
||||
{
|
||||
index++;
|
||||
if (p.WrapperType == WrapperTypes.GenericParameter)
|
||||
{
|
||||
p.Reference = false;
|
||||
p.Array = 3;
|
||||
p.Pointer = 0;
|
||||
p.Generic = true;
|
||||
p.CurrentType = "T" + index.ToString();
|
||||
p.Flow = FlowDirection.Undefined;
|
||||
func.Parameters.Rebuild = true;
|
||||
}
|
||||
}
|
||||
yield return func;
|
||||
}
|
||||
|
||||
static void WrapReturnType(Function func)
|
||||
{
|
||||
switch (func.ReturnType.WrapperType)
|
||||
if ((func.ReturnType.WrapperType & WrapperTypes.StringReturnType) != 0)
|
||||
{
|
||||
case WrapperTypes.StringReturnType:
|
||||
func.ReturnType.QualifiedType = "String";
|
||||
break;
|
||||
func.ReturnType.QualifiedType = "String";
|
||||
}
|
||||
|
||||
if ((func.ReturnType.WrapperType & WrapperTypes.GenericReturnType) != 0)
|
||||
{
|
||||
// Nothing else we can do, using generics will break the runtime
|
||||
func.ReturnType.QualifiedType = "IntPtr";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue