private TypeMemo AddStaticForwarders(TypeDefinition systemType) { var mod = systemType.Module; var intPtrRef = mod.ImportReference(typeof(IntPtr)); var intPtrToVoid = mod.ImportReference(intPtrRef.Resolve().Methods.FirstOrDefault(x => x.Name == nameof(IntPtr.ToPointer))); TypeMemo memo = default; memo.m_SystemType = systemType; memo.m_Wrappers = new MethodDefinition[3]; for (int i = 0; i < MethodNames.Length; ++i) { var name = MethodNames[i]; var methodDef = new MethodDefinition(GeneratedMethodNames[i], MethodAttributes.Static | MethodAttributes.Private, mod.ImportReference(typeof(void))); methodDef.Parameters.Add(new ParameterDefinition("self", ParameterAttributes.None, intPtrRef)); methodDef.Parameters.Add(new ParameterDefinition("state", ParameterAttributes.None, intPtrRef)); var targetMethod = systemType.Methods.FirstOrDefault(x => x.Name == name && x.Parameters.Count == 1).Resolve(); // Transfer any BurstCompile attribute from target function to the forwarding wrapper var burstAttribute = targetMethod.CustomAttributes.FirstOrDefault(x => x.Constructor.DeclaringType.Name == nameof(BurstCompileAttribute)); if (burstAttribute != null) { methodDef.CustomAttributes.Add(new CustomAttribute(burstAttribute.Constructor, burstAttribute.GetBlob())); memo.m_BurstCompileBits |= 1 << i; } var processor = methodDef.Body.GetILProcessor(); processor.Emit(OpCodes.Ldarga, 0); processor.Emit(OpCodes.Call, intPtrToVoid); processor.Emit(OpCodes.Ldarga, 1); processor.Emit(OpCodes.Call, intPtrToVoid); processor.Emit(OpCodes.Call, targetMethod); processor.Emit(OpCodes.Ret); systemType.Methods.Add(methodDef); memo.m_Wrappers[i] = methodDef; } return(memo); }
private TypeMemo AddStaticForwarders(TypeDefinition systemType) { var mod = systemType.Module; var intPtrRef = mod.ImportReference(typeof(IntPtr)); var intPtrToVoid = mod.ImportReference(intPtrRef.Resolve().Methods.FirstOrDefault(x => x.Name == nameof(IntPtr.ToPointer))); TypeMemo memo = default; memo.m_SystemType = systemType; memo.m_Wrappers = new MethodDefinition[5]; var hasStartStop = systemType.Interfaces.Any((x) => x.InterfaceType.FullName == "Unity.Entities.ISystemBaseStartStop"); for (int i = 0; i < MethodNames.Length; ++i) { var name = MethodNames[i]; var fullName = MethodFullNames[i]; // Cecil sees interface method names from other assemblies as the full namespaced name if (!hasStartStop && i >= 3) { break; } var methodDef = new MethodDefinition(GeneratedPrefix + name, MethodAttributes.Static | MethodAttributes.Assembly, mod.ImportReference(typeof(void))); methodDef.Parameters.Add(new ParameterDefinition("self", ParameterAttributes.None, intPtrRef)); methodDef.Parameters.Add(new ParameterDefinition("state", ParameterAttributes.None, intPtrRef)); var targetMethod = systemType.Methods.FirstOrDefault(x => x.Parameters.Count == 1 && (x.Name == name || x.Name == fullName)); if (targetMethod == null) { continue; } // Transfer any BurstCompile attribute from target function to the forwarding wrapper var burstAttribute = targetMethod.CustomAttributes.FirstOrDefault(x => x.Constructor.DeclaringType.Name == nameof(BurstCompileAttribute)); if (burstAttribute != null) { methodDef.CustomAttributes.Add(new CustomAttribute(burstAttribute.Constructor, burstAttribute.GetBlob())); memo.m_BurstCompileBits |= 1 << i; } #if UNITY_DOTSRUNTIME // Burst CompileFunctionPointer in DOTS Runtime will not currently decorate methods as [MonoPInvokeCallback] // so we add that here until that is supported var monoPInvokeCallbackAttributeConstructor = typeof(Jobs.MonoPInvokeCallbackAttribute).GetConstructor(Type.EmptyTypes); methodDef.CustomAttributes.Add(new CustomAttribute(mod.ImportReference(monoPInvokeCallbackAttributeConstructor))); #endif var processor = methodDef.Body.GetILProcessor(); processor.Emit(OpCodes.Ldarga, 0); processor.Emit(OpCodes.Call, intPtrToVoid); processor.Emit(OpCodes.Ldarga, 1); processor.Emit(OpCodes.Call, intPtrToVoid); processor.Emit(OpCodes.Call, targetMethod); processor.Emit(OpCodes.Ret); systemType.Methods.Add(methodDef); memo.m_Wrappers[i] = methodDef; } return(memo); }