diff --git a/Editor/ABI/TypeInfo.cs b/Editor/ABI/TypeInfo.cs index 9a6e7a0..01033b9 100644 --- a/Editor/ABI/TypeInfo.cs +++ b/Editor/ABI/TypeInfo.cs @@ -40,6 +40,8 @@ namespace HybridCLR.Editor.ABI public bool IsStruct => PorType == ParamOrReturnType.STRUCT; + public bool IsPrimitiveType => PorType <= ParamOrReturnType.U; + private readonly int _typeId; public int TypeId => _typeId; diff --git a/Editor/MethodBridge/Generator.cs b/Editor/MethodBridge/Generator.cs index 6c41f24..f1a0bff 100644 --- a/Editor/MethodBridge/Generator.cs +++ b/Editor/MethodBridge/Generator.cs @@ -539,14 +539,55 @@ static void __M2N_{method.CreateCallSigName()}(const MethodInfo* method, uint16_ "); } + public string GenerateArgumentSizeAndOffset(List paramInfos) + { + StringBuilder s = new StringBuilder(); + int index = 0; + foreach (var param in paramInfos) + { + s.AppendLine($"\tconstexpr int __ARG_OFFSET_{index}__ = {(index > 0 ? $"__ARG_OFFSET_{index - 1}__ + __ARG_SIZE_{index-1}__" : "0")};"); + s.AppendLine($"\tconstexpr int __ARG_SIZE_{index}__ = (sizeof(__arg{index}) + 7)/8;"); + index++; + } + s.AppendLine($"\tconstexpr int __TOTAL_ARG_SIZE__ = {(paramInfos.Count > 0 ? $"__ARG_OFFSET_{index-1}__ + __ARG_SIZE_{index-1}__" : "1")};"); + return s.ToString(); + } + + public string GenerateCopyArgumentToInterpreterStack(List paramInfos, bool adjustorThunk) + { + StringBuilder s = new StringBuilder(); + int index = 0; + foreach (var param in paramInfos) + { + if (param.Type.IsPrimitiveType) + { + if (param.Type.NeedExpandValue()) + { + s.AppendLine($"\targs[__ARG_OFFSET_{index}__].u64 = {(index == 0 && adjustorThunk ? $"(uint64_t)((uintptr_t)__arg{index} + sizeof(Il2CppObject))" : $"__arg{index}")};"); + } + else + { + s.AppendLine($"\t*({param.Type.GetTypeName()}*)(args + __ARG_OFFSET_{index}__) = {(index == 0 && adjustorThunk ? $"(uintptr_t)__arg{index} + sizeof(Il2CppObject)" : $"__arg{index}")};"); + } + } + else + { + s.AppendLine($"\t*({param.Type.GetTypeName()}*)(args + __ARG_OFFSET_{index}__) = __arg{index};"); + } + index++; + } + return s.ToString(); + } + public void GenerateNative2ManagedMethod(MethodDesc method, List lines) { string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" })); - lines.Add($@" static {method.ReturnInfo.Type.GetTypeName()} __N2M_{method.CreateCallSigName()}({paramListStr}) {{ - StackObject args[{Math.Max(1, method.ParamInfos.Count)}] = {{{string.Join(", ", method.ParamInfos.Select(p => GetNative2ManagedPassParam(p.Type, $"__arg{p.Index}")))} }}; +{GenerateArgumentSizeAndOffset(method.ParamInfos)} + StackObject args[__TOTAL_ARG_SIZE__]; +{GenerateCopyArgumentToInterpreterStack(method.ParamInfos, false)} {(method.ReturnInfo.IsVoid ? "Interpreter::Execute(method, args, nullptr);" : $"{method.ReturnInfo.Type.GetTypeName()} ret; Interpreter::Execute(method, args, &ret); return ret;")} }} "); @@ -554,13 +595,14 @@ static {method.ReturnInfo.Type.GetTypeName()} __N2M_{method.CreateCallSigName()} public void GenerateAdjustThunkMethod(MethodDesc method, List lines) { - int totalQuadWordNum = method.ParamInfos.Count; string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" })); lines.Add($@" static {method.ReturnInfo.Type.GetTypeName()} __N2M_AdjustorThunk_{method.CreateCallSigName()}({paramListStr}) {{ - StackObject args[] = {{{string.Join(", ", method.ParamInfos.Select(p => (p.Index == 0 ? $"(uint64_t)(*(uint8_t**)&__arg{p.Index} + sizeof(Il2CppObject))" : GetNative2ManagedPassParam(p.Type, $"__arg{p.Index}"))))} }}; +{GenerateArgumentSizeAndOffset(method.ParamInfos)} + StackObject args[__TOTAL_ARG_SIZE__]; +{GenerateCopyArgumentToInterpreterStack(method.ParamInfos, true)} {(method.ReturnInfo.IsVoid ? "Interpreter::Execute(method, args, nullptr);" : $"{method.ReturnInfo.Type.GetTypeName()} ret; Interpreter::Execute(method, args, &ret); return ret;")} }} ");