diff --git a/Editor/ABI/ABIUtil.cs b/Editor/ABI/ABIUtil.cs index 53939e0..43846b0 100644 --- a/Editor/ABI/ABIUtil.cs +++ b/Editor/ABI/ABIUtil.cs @@ -15,6 +15,7 @@ namespace HybridCLR.Editor.ABI case PlatformABI.Arm64: return "HYBRIDCLR_ABI_ARM_64"; case PlatformABI.Universal64: return "HYBRIDCLR_ABI_UNIVERSAL_64"; case PlatformABI.Universal32: return "HYBRIDCLR_ABI_UNIVERSAL_32"; + case PlatformABI.WebGL32: return "HYBRIDCLR_ABI_WEBGL32"; default: throw new NotSupportedException(); } } diff --git a/Editor/ABI/PlatformABI.cs b/Editor/ABI/PlatformABI.cs index 9b082bb..62fdb16 100644 --- a/Editor/ABI/PlatformABI.cs +++ b/Editor/ABI/PlatformABI.cs @@ -5,5 +5,6 @@ Universal32, Universal64, Arm64, + WebGL32, } } diff --git a/Editor/ABI/TypeCreatorBase.cs b/Editor/ABI/TypeCreatorBase.cs index 873ef7b..54b3ffd 100644 --- a/Editor/ABI/TypeCreatorBase.cs +++ b/Editor/ABI/TypeCreatorBase.cs @@ -14,6 +14,8 @@ namespace HybridCLR.Editor.ABI public virtual bool IsSupportHFA => false; + public virtual bool IsSupportSingletonStruct => false; + public TypeInfo GetNativeIntTypeInfo() => IsArch32 ? TypeInfo.s_i4 : TypeInfo.s_i8; public ValueTypeSizeAligmentCalculator Calculator => IsArch32 ? ValueTypeSizeAligmentCalculator.Caculator32 : ValueTypeSizeAligmentCalculator.Caculator64; @@ -170,6 +172,78 @@ namespace HybridCLR.Editor.ABI 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 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; + } + protected static TypeInfo CreateGeneralValueType(TypeSig type, int size, int aligment) { System.Diagnostics.Debug.Assert(size % aligment == 0); @@ -197,6 +271,10 @@ namespace HybridCLR.Editor.ABI default: throw new NotSupportedException(); } } + //else if(IsSupportSingletonStruct && TryComputSingletonStruct(type, out var ssTypeInfo)) + //{ + // return CreateTypeInfo(ssTypeInfo.Type); + //} else { // 64位下结构体内存对齐规则是一样的 diff --git a/Editor/ABI/TypeCreatorFactory.cs b/Editor/ABI/TypeCreatorFactory.cs index eb265c0..42393b7 100644 --- a/Editor/ABI/TypeCreatorFactory.cs +++ b/Editor/ABI/TypeCreatorFactory.cs @@ -15,6 +15,7 @@ namespace HybridCLR.Editor.ABI case PlatformABI.Arm64: return new TypeCreatorArm64(); case PlatformABI.Universal32: return new TypeCreatorUniversal32(); case PlatformABI.Universal64: return new TypeCreatorUniversal64(); + case PlatformABI.WebGL32: return new TypeCreatorWebGL32(); default: throw new NotSupportedException(abi.ToString()); } } diff --git a/Editor/ABI/TypeCreatorWebGL32.cs b/Editor/ABI/TypeCreatorWebGL32.cs new file mode 100644 index 0000000..0309acc --- /dev/null +++ b/Editor/ABI/TypeCreatorWebGL32.cs @@ -0,0 +1,34 @@ +using dnlib.DotNet; +using HybridCLR.Editor.Meta; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HybridCLR.Editor.ABI +{ + public class SingletonStruct + { + public TypeSig Type { get; set; } + } + + public class TypeCreatorWebGL32 : TypeCreatorBase + { + public override bool IsArch32 => true; + + public override bool IsSupportHFA => false; + + public override bool IsSupportSingletonStruct => true; + + + protected override TypeInfo OptimizeSigType(TypeInfo type, bool returnType) + { + //if (type.PorType > ParamOrReturnType.STRUCTURE_ALIGN1 && type.PorType <= ParamOrReturnType.STRUCTURE_ALIGN4) + //{ + // return new TypeInfo(ParamOrReturnType.STRUCTURE_ALIGN1, type.Size); + //} + return type; + } + } +} diff --git a/Editor/ABI/TypeCreatorWebGL32.cs.meta b/Editor/ABI/TypeCreatorWebGL32.cs.meta new file mode 100644 index 0000000..a6affdc --- /dev/null +++ b/Editor/ABI/TypeCreatorWebGL32.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4790a87aacda1a14d813570e9e0f35ca +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/BuildProcessors/PatchScriptingAssemblyList.cs b/Editor/BuildProcessors/PatchScriptingAssemblyList.cs index 21269db..8b7d59a 100644 --- a/Editor/BuildProcessors/PatchScriptingAssemblyList.cs +++ b/Editor/BuildProcessors/PatchScriptingAssemblyList.cs @@ -81,7 +81,7 @@ namespace HybridCLR.Editor.BuildProcessors if (jsonFiles.Length == 0) { - Debug.LogError($"can not find file {SettingsUtil.ScriptingAssembliesJsonFile}"); + //Debug.LogError($"can not find file {SettingsUtil.ScriptingAssembliesJsonFile}"); return; } diff --git a/Editor/MethodBridge/Generator.cs b/Editor/MethodBridge/Generator.cs index cc6e71f..c6b9281 100644 --- a/Editor/MethodBridge/Generator.cs +++ b/Editor/MethodBridge/Generator.cs @@ -74,6 +74,7 @@ namespace HybridCLR.Editor.MethodBridge case PlatformABI.Universal32: return new PlatformGeneratorUniversal32(); case PlatformABI.Universal64: return new PlatformGeneratorUniversal64(); case PlatformABI.Arm64: return new PlatformGeneratorArm64(); + case PlatformABI.WebGL32: return new PlatformGeneratorWebGL32(); default: throw new NotSupportedException(); } } diff --git a/Editor/MethodBridge/PlatformGeneratorUniversal32.cs b/Editor/MethodBridge/PlatformGeneratorUniversal32.cs index 918ae5f..7feab81 100644 --- a/Editor/MethodBridge/PlatformGeneratorUniversal32.cs +++ b/Editor/MethodBridge/PlatformGeneratorUniversal32.cs @@ -14,14 +14,6 @@ namespace HybridCLR.Editor.MethodBridge { public override PlatformABI PlatformABI { get; } = PlatformABI.Universal32; - //protected override TypeInfo CreateValueType(TypeSig type, bool returnValue) - //{ - // (int typeSize, int typeAligment) = ComputeSizeAndAligmentOfArch32(type); - // int actualAliment = typeAligment <= 4 ? 1 : 8; - // return CreateGeneralValueType(type, typeSize, actualAliment); - //} - - public override void GenerateManaged2NativeMethod(MethodDesc method, List lines) { string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" })); diff --git a/Editor/MethodBridge/PlatformGeneratorWebGL32.cs b/Editor/MethodBridge/PlatformGeneratorWebGL32.cs new file mode 100644 index 0000000..1269201 --- /dev/null +++ b/Editor/MethodBridge/PlatformGeneratorWebGL32.cs @@ -0,0 +1,68 @@ +using dnlib.DotNet; +using HybridCLR.Editor.ABI; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace HybridCLR.Editor.MethodBridge +{ + public class PlatformGeneratorWebGL32 : PlatformGeneratorBase + { + public override PlatformABI PlatformABI { get; } = PlatformABI.WebGL32; + + + public override void GenerateManaged2NativeMethod(MethodDesc method, List lines) + { + string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" })); + string paramNameListStr = string.Join(", ", method.ParamInfos.Select(p => p.Managed2NativeParamValue(this.PlatformABI)).Concat(new string[] { "method" })); + + lines.Add($@" +// {method.MethodDef} +static void __M2N_{method.CreateCallSigName()}(const MethodInfo* method, uint16_t* argVarIndexs, StackObject* localVarBase, void* ret) +{{ + typedef {method.ReturnInfo.Type.GetTypeName()} (*NativeMethod)({paramListStr}); + {(!method.ReturnInfo.IsVoid ? $"*({method.ReturnInfo.Type.GetTypeName()}*)ret = " : "")}((NativeMethod)(method->methodPointerCallByInterp))({paramNameListStr}); +}} +"); + } + public override void GenerateNative2ManagedMethod(MethodDesc method, List lines) + { + int totalQuadWordNum = method.ParamInfos.Count + method.ReturnInfo.GetParamSlotNum(this.PlatformABI); + string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" })); + + lines.Add($@" +// {method.MethodDef} +static {method.ReturnInfo.Type.GetTypeName()} __N2M_{method.CreateCallSigName()}({paramListStr}) +{{ + StackObject args[{Math.Max(totalQuadWordNum, 1)}] = {{{string.Join(", ", method.ParamInfos.Select(p => p.Native2ManagedParamValue(this.PlatformABI)))} }}; + StackObject* ret = {(method.ReturnInfo.IsVoid ? "nullptr" : "args + " + method.ParamInfos.Count)}; + Interpreter::Execute(method, args, ret); + {(!method.ReturnInfo.IsVoid ? $"return *({method.ReturnInfo.Type.GetTypeName()}*)ret;" : "")} +}} +"); + } + public override void GenerateAdjustThunkMethod(MethodDesc method, List lines) + { + int totalQuadWordNum = method.ParamInfos.Count + method.ReturnInfo.GetParamSlotNum(this.PlatformABI); + + string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" })); + + lines.Add($@" +// {method.MethodDef} +static {method.ReturnInfo.Type.GetTypeName()} __N2M_AdjustorThunk_{method.CreateCallSigName()}({paramListStr}) +{{ + StackObject args[{Math.Max(totalQuadWordNum, 1)}] = {{{string.Join(", ", method.ParamInfos.Select(p => (p.Index == 0 ? $"(uint64_t)(*(uint8_t**)&__arg{p.Index} + sizeof(Il2CppObject))" : p.Native2ManagedParamValue(this.PlatformABI))))} }}; + StackObject* ret = {(method.ReturnInfo.IsVoid ? "nullptr" : "args + " + method.ParamInfos.Count)}; + Interpreter::Execute(method, args, ret); + {(!method.ReturnInfo.IsVoid ? $"return *({method.ReturnInfo.Type.GetTypeName()}*)ret;" : "")} +}} +"); + + } + } + +} diff --git a/Editor/MethodBridge/PlatformGeneratorWebGL32.cs.meta b/Editor/MethodBridge/PlatformGeneratorWebGL32.cs.meta new file mode 100644 index 0000000..d2d988b --- /dev/null +++ b/Editor/MethodBridge/PlatformGeneratorWebGL32.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2912d21f60f4c684785c31efcf2d9b29 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package.json b/package.json index a180a43..a26ed0d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "com.focus-creative-games.hybridclr_unity", - "version": "0.6.1", + "version": "0.7.0", "displayName": "HybridCLR", "description": "Unity package for HybridCLR. It includes editor and runtime scripts and assets for HybridCLR", "category": "Runtime",