Skip to content

Commit

Permalink
[fix] 修复WebGL平台ABI的bug
Browse files Browse the repository at this point in the history
  • Loading branch information
walon committed Jun 3, 2023
1 parent 8439e41 commit 21b85aa
Show file tree
Hide file tree
Showing 5 changed files with 309 additions and 206 deletions.
96 changes: 94 additions & 2 deletions Editor/ABI/TypeCreatorArm64.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ public class TypeCreatorArm64 : TypeCreatorBase
{
public override bool IsArch32 => false;

public override bool IsSupportHFA => true;

protected override TypeInfo OptimizeSigType(TypeInfo type, bool returnType)
{
if (!type.IsGeneralValueType)
Expand All @@ -42,5 +40,99 @@ protected override TypeInfo OptimizeSigType(TypeInfo type, bool returnType)
}
return TypeInfo.s_ref;
}


private static bool IsNotHFAFastCheck(int typeSize)
{
return typeSize % 4 != 0 || typeSize > 32;
}

private static bool ComputHFATypeInfo0(TypeSig type, HFATypeInfo typeInfo)
{
TypeDef typeDef = type.ToTypeDefOrRef().ResolveTypeDefThrow();

List<TypeSig> klassInst = type.ToGenericInstSig()?.GenericArguments?.ToList();
GenericArgumentContext ctx = klassInst != null ? new GenericArgumentContext(klassInst, null) : null;

var fields = typeDef.Fields;// typeDef.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (FieldDef field in fields)
{
if (field.IsStatic)
{
continue;
}
TypeSig ftype = ctx != null ? MetaUtil.Inflate(field.FieldType, ctx) : field.FieldType;
switch (ftype.ElementType)
{
case ElementType.R4:
case ElementType.R8:
{
if (ftype == typeInfo.Type || typeInfo.Type == null)
{
typeInfo.Type = ftype;
++typeInfo.Count;
}
else
{
return false;
}
break;
}
case ElementType.ValueType:
{
if (!ComputHFATypeInfo0(ftype, typeInfo))
{
return false;
}
break;
}
case ElementType.GenericInst:
{
if (!ftype.IsValueType || !ComputHFATypeInfo0(ftype, typeInfo))
{
return false;
}
break;
}
default: return false;
}
}
return typeInfo.Count <= 4;
}

private static bool ComputHFATypeInfo(TypeSig type, int typeSize, out HFATypeInfo typeInfo)
{
typeInfo = new HFATypeInfo();
if (IsNotHFAFastCheck(typeSize))
{
return false;
}
bool ok = ComputHFATypeInfo0(type, typeInfo);
if (ok && typeInfo.Count >= 1 && typeInfo.Count <= 4)
{
int fieldSize = typeInfo.Type.ElementType == ElementType.R4 ? 4 : 8;
return typeSize == fieldSize * typeInfo.Count;
}
return false;
}

protected override bool TryCreateCustomValueTypeInfo(TypeSig type, int typeSize, int typeAligment, out TypeInfo typeInfo)
{
if (ComputHFATypeInfo(type, typeSize, out HFATypeInfo hfaTypeInfo))
{
bool isFloat = hfaTypeInfo.Type.ElementType == ElementType.R4;
switch (hfaTypeInfo.Count)
{
case 1: typeInfo = isFloat ? TypeInfo.s_r4 : TypeInfo.s_r8; break;
case 2: typeInfo = isFloat ? TypeInfo.s_vf2 : TypeInfo.s_vd2; break;
case 3: typeInfo = isFloat ? TypeInfo.s_vf3 : TypeInfo.s_vd3; break;
case 4: typeInfo = isFloat ? TypeInfo.s_vf4 : TypeInfo.s_vd4; break;
default: throw new NotSupportedException();
}
return true;
}
typeInfo = null;
return false;
}
}
}
216 changes: 22 additions & 194 deletions Editor/ABI/TypeCreatorBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,16 @@ public abstract class TypeCreatorBase
{
public abstract bool IsArch32 { get; }

public virtual bool IsSupportHFA => false;

public virtual bool IsSupportWebGLSpecialValueType => false;

public TypeInfo GetNativeIntTypeInfo() => IsArch32 ? TypeInfo.s_i4 : TypeInfo.s_i8;

public ValueTypeSizeAligmentCalculator Calculator => IsArch32 ? ValueTypeSizeAligmentCalculator.Caculator32 : ValueTypeSizeAligmentCalculator.Caculator64;


private readonly Dictionary<TypeSig, (int, int)> _typeSizeCache = new Dictionary<TypeSig, (int, int)>(TypeEqualityComparer.Instance);


private readonly Dictionary<TypeSig, TypeInfo> _typeInfoCache = new Dictionary<TypeSig, TypeInfo>(TypeEqualityComparer.Instance);

public (int Size, int Aligment) ComputeSizeAndAligment(TypeSig t)
{
if (_typeSizeCache.TryGetValue(t, out var sizeAndAligment))
Expand All @@ -36,6 +35,16 @@ public abstract class TypeCreatorBase
}

public TypeInfo CreateTypeInfo(TypeSig type)
{
if (!_typeInfoCache.TryGetValue(type, out var typeInfo))
{
typeInfo = CreateTypeInfo0(type);
_typeInfoCache.Add(type, typeInfo);
}
return new TypeInfo(typeInfo.PorType, typeInfo.Size);
}

TypeInfo CreateTypeInfo0(TypeSig type)
{
type = type.RemovePinnedAndModifiers();
if (type.IsByRef)
Expand Down Expand Up @@ -103,175 +112,6 @@ public TypeInfo CreateTypeInfo(TypeSig type)
}
}

private static bool IsNotHFAFastCheck(int typeSize)
{
return typeSize % 4 != 0 || typeSize > 32;
}

private static bool ComputHFATypeInfo0(TypeSig type, HFATypeInfo typeInfo)
{
TypeDef typeDef = type.ToTypeDefOrRef().ResolveTypeDefThrow();

List<TypeSig> klassInst = type.ToGenericInstSig()?.GenericArguments?.ToList();
GenericArgumentContext ctx = klassInst != null ? new GenericArgumentContext(klassInst, null) : null;

var fields = typeDef.Fields;// typeDef.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (FieldDef field in fields)
{
if (field.IsStatic)
{
continue;
}
TypeSig ftype = ctx != null ? MetaUtil.Inflate(field.FieldType, ctx) : field.FieldType;
switch (ftype.ElementType)
{
case ElementType.R4:
case ElementType.R8:
{
if (ftype == typeInfo.Type || typeInfo.Type == null)
{
typeInfo.Type = ftype;
++typeInfo.Count;
}
else
{
return false;
}
break;
}
case ElementType.ValueType:
{
if (!ComputHFATypeInfo0(ftype, typeInfo))
{
return false;
}
break;
}
case ElementType.GenericInst:
{
if (!ftype.IsValueType || !ComputHFATypeInfo0(ftype, typeInfo))
{
return false;
}
break;
}
default: return false;
}
}
return typeInfo.Count <= 4;
}

private static bool ComputHFATypeInfo(TypeSig type, int typeSize, out HFATypeInfo typeInfo)
{
typeInfo = new HFATypeInfo();
if (IsNotHFAFastCheck(typeSize))
{
return false;
}
bool ok = ComputHFATypeInfo0(type, typeInfo);
if (ok && typeInfo.Count >= 1 && typeInfo.Count <= 4)
{
int fieldSize = typeInfo.Type.ElementType == ElementType.R4 ? 4 : 8;
return typeSize == fieldSize * typeInfo.Count;
}
return false;
}

public static bool TryComputSingletonStruct(TypeSig type, out SingletonStruct result)
{
result = new SingletonStruct();
return TryComputSingletonStruct0(type, result) && result.Type != null;
}

public static bool TryComputSingletonStruct0(TypeSig type, SingletonStruct result)
{
TypeDef typeDef = type.ToTypeDefOrRef().ResolveTypeDefThrow();
if (typeDef.IsEnum)
{
if (result.Type == null)
{
result.Type = typeDef.GetEnumUnderlyingType();
return true;
}
else
{
return false;
}
}

List<TypeSig> klassInst = type.ToGenericInstSig()?.GenericArguments?.ToList();
GenericArgumentContext ctx = klassInst != null ? new GenericArgumentContext(klassInst, null) : null;

var fields = typeDef.Fields;// typeDef.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (FieldDef field in fields)
{
if (field.IsStatic)
{
continue;
}
TypeSig ftype = ctx != null ? MetaUtil.Inflate(field.FieldType, ctx) : field.FieldType;

switch (ftype.ElementType)
{
case ElementType.TypedByRef: return false;
case ElementType.ValueType:
{
if (!TryComputSingletonStruct0(ftype, result))
{
return false;
}
break;
}
case ElementType.GenericInst:
{
if (!ftype.IsValueType)
{
goto default;
}
if (!TryComputSingletonStruct0(ftype, result))
{
return false;
}
break;
}
default:
{
if (result.Type != null)
{
return false;
}
result.Type = ftype;
break;
}
}
}

return true;
}

public static bool IsWebGLSpeicalValueType(TypeSig type)
{
TypeDef typeDef = type.ToTypeDefOrRef().ResolveTypeDefThrow();
if (typeDef.IsEnum)
{
return false;
}
var fields = typeDef.Fields;// typeDef.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (fields.Count == 0)
{
return true;
}
if (fields.All(f => f.IsStatic))
{
return true;
}
if (typeDef.IsExplicitLayout && fields.Count(f => !f.IsStatic) > 1)
{
return true;
}
return false;
}

protected static TypeInfo CreateGeneralValueType(TypeSig type, int size, int aligment)
{
System.Diagnostics.Debug.Assert(size % aligment == 0);
Expand All @@ -285,31 +125,19 @@ protected static TypeInfo CreateGeneralValueType(TypeSig type, int size, int ali
}
}

protected virtual bool TryCreateCustomValueTypeInfo(TypeSig type, int typeSize, int typeAligment, out TypeInfo typeInfo)
{
typeInfo = null;
return false;
}

protected TypeInfo CreateValueType(TypeSig type)
{
(int typeSize, int typeAligment) = ComputeSizeAndAligment(type);
if (IsSupportHFA && ComputHFATypeInfo(type, typeSize, out HFATypeInfo hfaTypeInfo))
{
bool isFloat = hfaTypeInfo.Type.ElementType == ElementType.R4;
switch (hfaTypeInfo.Count)
{
case 1: return isFloat ? TypeInfo.s_r4 : TypeInfo.s_r8;
case 2: return isFloat ? TypeInfo.s_vf2 : TypeInfo.s_vd2;
case 3: return isFloat ? TypeInfo.s_vf3 : TypeInfo.s_vd3;
case 4: return isFloat ? TypeInfo.s_vf4 : TypeInfo.s_vd4;
default: throw new NotSupportedException();
}
}
if (IsSupportWebGLSpecialValueType && IsWebGLSpeicalValueType(type))
if (TryCreateCustomValueTypeInfo(type, typeSize, typeAligment, out var typeInfo))
{
switch (typeAligment)
{
case 1: return new TypeInfo(ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN1, typeSize);
case 2: return new TypeInfo(ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN2, typeSize);
case 4: return new TypeInfo(ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN4, typeSize);
case 8: return new TypeInfo(ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN8, typeSize);
default: throw new NotSupportedException();
}
Debug.Log($"[{GetType().Name}] CustomeValueType:{type} => {typeInfo.CreateSigName()}");
return typeInfo;
}
else
{
Expand Down
2 changes: 0 additions & 2 deletions Editor/ABI/TypeCreatorUniversal32.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ public class TypeCreatorUniversal32 : TypeCreatorBase
{
public override bool IsArch32 => true;

public override bool IsSupportHFA => false;

protected override TypeInfo OptimizeSigType(TypeInfo type, bool returnType)
{
if (type.PorType > ParamOrReturnType.STRUCTURE_ALIGN1 && type.PorType <= ParamOrReturnType.STRUCTURE_ALIGN4)
Expand Down
5 changes: 2 additions & 3 deletions Editor/ABI/TypeCreatorUniversal64.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
Expand All @@ -10,8 +11,6 @@ public class TypeCreatorUniversal64 : TypeCreatorBase
{
public override bool IsArch32 => false;

public override bool IsSupportHFA => false;

protected override TypeInfo OptimizeSigType(TypeInfo type, bool returnType)
{
if (type.PorType > ParamOrReturnType.STRUCTURE_ALIGN1 && type.PorType <= ParamOrReturnType.STRUCTURE_ALIGN8)
Expand Down
Loading

0 comments on commit 21b85aa

Please sign in to comment.