private void EmitFunctionParamInit(ILProcessor processor, ManagedUnrealFunctionInfo functionInfo, ManagedUnrealPropertyInfo paramInfo, VariableDefinition paramsBuffer, FieldDefinition nativePropertyField) { if (!codeSettings.LazyFunctionParamInitDestroy && ManagedUnrealTypeInfo.PropertyRequiresInit(paramInfo)) { // Ensure the checks to include the native field prop are in sync with this function Debug.Assert(nativePropertyField != null); // NativeReflection.InitializeValue_InContainer(XXXX_YYYY_PropertyAddress.Address, ParamsBuffer) EmitLdNativePropertyFieldAddress(processor, nativePropertyField); processor.Emit(OpCodes.Ldloc, paramsBuffer); processor.Emit(OpCodes.Call, reflectionInitializeValue_InContainer); } }
private void WriteNativeFunctionInvokerBody(TypeDefinition type, ManagedUnrealTypeInfo typeInfo, ManagedUnrealFunctionInfo functionInfo, MethodDefinition method, InjectedMembers injectedMembers, Dictionary <ManagedUnrealPropertyInfo, ParameterDefinition> parameters, ILProcessor processor, bool isDelegate, bool perInstanceFunctionAddress) { FieldDefinition functionAddressField = injectedMembers.GetFunctionAddress(functionInfo); FieldDefinition paramsSizeField = injectedMembers.GetFunctionParamsSize(functionInfo); if (perInstanceFunctionAddress && injectedMembers.GetFunctionAddressPerInstance(functionInfo) == null) { functionAddressField = AddNativeFunctionField(type, functionInfo, false); injectedMembers.SetFunctionAddressPerInstance(functionInfo, functionAddressField); } VariableDefinition bufferAllocation = new VariableDefinition(bytePtrTypeRef); method.Body.Variables.Add(bufferAllocation); VariableDefinition paramsBuffer = new VariableDefinition(intPtrTypeRef); method.Body.Variables.Add(paramsBuffer); Instruction loadBuffer = processor.Create(OpCodes.Ldloc, paramsBuffer); Instruction loadOwner = processor.Create(OpCodes.Ldnull); // byte* ParamsBufferAllocation = stackalloc byte[XXXX_ParamsSize]; // IntPtr ParamsBuffer = new IntPtr(ParamsBufferAllocation); processor.Emit(OpCodes.Ldsfld, paramsSizeField); processor.Emit(OpCodes.Conv_U); processor.Emit(OpCodes.Localloc); processor.Emit(OpCodes.Stloc, bufferAllocation); processor.Emit(OpCodes.Ldloca, paramsBuffer); processor.Emit(OpCodes.Ldloc, bufferAllocation); processor.Emit(OpCodes.Call, intPtrConstructorMethod); if (codeSettings.LazyFunctionParamInitDestroy) { // NativeReflection.InvokeFunction_InitAll(XXXX_FunctionAddress, ParamsBuffer); if (functionAddressField.IsStatic) { processor.Emit(OpCodes.Ldsfld, functionAddressField); } else { processor.Emit(OpCodes.Ldarg_0); processor.Emit(OpCodes.Ldfld, functionAddressField); } processor.Emit(OpCodes.Ldloc, paramsBuffer); processor.Emit(OpCodes.Call, reflectionInitAllMethod); } else if (codeSettings.MemzeroStackalloc || codeSettings.MemzeroStackallocOnlyIfOut) { bool requiresMemzero = codeSettings.MemzeroStackalloc; if (codeSettings.MemzeroStackallocOnlyIfOut) { // Memzero only if there is a return value or a (non ref) out param which doesn't have a zero constructor. // (if the param can't be zero initialized it will be initialized with a call to InitializeValue anyway) foreach (KeyValuePair <ManagedUnrealPropertyInfo, ParameterDefinition> param in parameters) { ManagedUnrealPropertyInfo paramInfo = param.Key; if (paramInfo.IsOut && !ManagedUnrealTypeInfo.PropertyRequiresInit(paramInfo)) { requiresMemzero = true; break; } } if (functionInfo.ReturnProp != null && !ManagedUnrealTypeInfo.PropertyRequiresInit(functionInfo.ReturnProp)) { requiresMemzero = true; } } if (requiresMemzero) { // FMemory.Memzero(ParamsBuffer, XXXX_ParamsSize processor.Emit(OpCodes.Ldloc, paramsBuffer); processor.Emit(OpCodes.Ldsfld, paramsSizeField); processor.Emit(OpCodes.Call, fmemoryMemzero); processor.Emit(OpCodes.Pop);// Memzero returns a value, pop it off the stack } } Instruction loadParamBufferInstruction = processor.Create(OpCodes.Ldloc, paramsBuffer); Dictionary <ManagedUnrealPropertyInfo, FieldDefinition> paramOffsets = new Dictionary <ManagedUnrealPropertyInfo, FieldDefinition>(); Dictionary <ManagedUnrealPropertyInfo, VariableDefinition> paramMarshalerVars = new Dictionary <ManagedUnrealPropertyInfo, VariableDefinition>(); foreach (KeyValuePair <ManagedUnrealPropertyInfo, ParameterDefinition> param in parameters) { ManagedUnrealPropertyInfo paramInfo = param.Key; FieldDefinition offsetField = injectedMembers.GetFunctionParamOffset(functionInfo, paramInfo); FieldDefinition nativePropertyField = injectedMembers.GetFunctionParamPropertyAddress(functionInfo, paramInfo); VariableDefinition marshalerVar = EmitCreateMarshaler(processor, loadBuffer, offsetField, nativePropertyField, paramInfo); if (marshalerVar != null) { method.Body.Variables.Add(marshalerVar); paramMarshalerVars[paramInfo] = marshalerVar; } // Init the param memory if required EmitFunctionParamInit(processor, functionInfo, paramInfo, paramsBuffer, nativePropertyField); // Write the parameter to the native buffer if it isn't an "out" parameter // XXXXMarshaler.ToNative(IntPtr.Add(ParamsBuffer, XXXX_YYYY_Offset), YYYY); if (!paramInfo.IsOut) { EmitStore(processor, loadParamBufferInstruction, offsetField, nativePropertyField, typeInfo, param.Key, marshalerVar, param.Value); } } if (functionInfo.ReturnProp != null) { // Init the return value memory if required EmitFunctionParamInit(processor, functionInfo, functionInfo.ReturnProp, paramsBuffer, injectedMembers.GetFunctionParamPropertyAddress(functionInfo, functionInfo.ReturnProp)); } if (isDelegate) { // ProcessDelegate(ParamsBuffer); MethodReference processDelegateMethod = assembly.MainModule.ImportEx(GetTypeFromTypeDefinition(type).GetMethod("ProcessDelegate")); processor.Emit(OpCodes.Ldarg_0); processor.Emit(OpCodes.Ldloc, paramsBuffer); processor.Emit(OpCodes.Callvirt, processDelegateMethod); } else { // NativeReflection.InvokeFunction(Address, XXXX_FunctionAddress, ParamsBuffer, XXXX_ParamsSize); processor.Emit(OpCodes.Ldarg_0); processor.Emit(OpCodes.Call, typeInfo.IsInterface ? iinterfaceImplAddressGetter : uobjectAddressGetter); if (functionAddressField.IsStatic) { processor.Emit(OpCodes.Ldsfld, functionAddressField); } else { processor.Emit(OpCodes.Ldarg_0); processor.Emit(OpCodes.Ldfld, functionAddressField); } processor.Emit(OpCodes.Ldloc, paramsBuffer); processor.Emit(OpCodes.Ldsfld, paramsSizeField); processor.Emit(OpCodes.Call, reflectionInvokeFunctionMethod); } VariableDefinition returnVar = null; if (functionInfo.ReturnProp != null) { returnVar = new VariableDefinition(assembly.MainModule.ImportEx(ManagedUnrealTypeInfo.GetTypeFromPropertyInfo(functionInfo.ReturnProp))); method.Body.Variables.Add(returnVar); VariableDefinition returnVarMarshaler = EmitCreateMarshaler(processor, loadBuffer, injectedMembers.GetFunctionParamOffset(functionInfo, functionInfo.ReturnProp), injectedMembers.GetFunctionParamPropertyAddress(functionInfo, functionInfo.ReturnProp), functionInfo.ReturnProp); if (returnVarMarshaler != null) { method.Body.Variables.Add(returnVarMarshaler); } FieldDefinition offsetField = injectedMembers.GetFunctionParamOffset(functionInfo, functionInfo.ReturnProp); FieldDefinition nativePropertyField = injectedMembers.GetFunctionParamPropertyAddress(functionInfo, functionInfo.ReturnProp); EmitLoad(processor, loadBuffer, offsetField, nativePropertyField, typeInfo, functionInfo.ReturnProp, returnVarMarshaler, returnVar); // Destroy the return value memory if required EmitFunctionParamDestroy(processor, functionInfo, functionInfo.ReturnProp, paramsBuffer, injectedMembers.GetFunctionParamPropertyAddress(functionInfo, functionInfo.ReturnProp)); } foreach (KeyValuePair <ManagedUnrealPropertyInfo, ParameterDefinition> param in parameters) { ManagedUnrealPropertyInfo paramInfo = param.Key; if (paramInfo.IsByRef || paramInfo.IsOut || paramInfo.IsCollection) { FieldDefinition offsetField = injectedMembers.GetFunctionParamOffset(functionInfo, paramInfo); FieldDefinition nativePropertyField = injectedMembers.GetFunctionParamPropertyAddress(functionInfo, paramInfo); VariableDefinition marshalerVar; paramMarshalerVars.TryGetValue(paramInfo, out marshalerVar); EmitLoad(processor, loadBuffer, offsetField, nativePropertyField, typeInfo, paramInfo, marshalerVar, param.Value); } // Destroy the param memory if required EmitFunctionParamDestroy(processor, functionInfo, paramInfo, paramsBuffer, injectedMembers.GetFunctionParamPropertyAddress(functionInfo, paramInfo)); } if (codeSettings.LazyFunctionParamInitDestroy) { // NativeReflection.InvokeFunction_DestroyAll(XXXX_FunctionAddress, ParamsBuffer); if (functionAddressField.IsStatic) { processor.Emit(OpCodes.Ldsfld, functionAddressField); } else { processor.Emit(OpCodes.Ldarg_0); processor.Emit(OpCodes.Ldfld, functionAddressField); } processor.Emit(OpCodes.Ldloc, paramsBuffer); processor.Emit(OpCodes.Call, reflectionDestroyAllMethod); } if (returnVar != null) { processor.Emit(OpCodes.Ldloc, returnVar); } processor.Emit(OpCodes.Ret); if (!functionAddressField.IsStatic) { // if (XXXX_FunctionAddress == IntPtr.Zero) { XXXX_FunctionAddress = NativeReflection.GetFunctionFromInstance(Address, "XXXX"); } Instruction branchTarget = processor.Body.Instructions[0]; processor.InsertBefore(branchTarget, processor.Create(OpCodes.Ldarg_0)); processor.InsertBefore(branchTarget, processor.Create(OpCodes.Ldfld, functionAddressField)); processor.InsertBefore(branchTarget, processor.Create(OpCodes.Ldsfld, intPtrZeroFieldRef)); processor.InsertBefore(branchTarget, processor.Create(OpCodes.Call, intPtrEqualsMethod)); Instruction branchPosition = processor.Create(OpCodes.Ldarg_0); processor.InsertBefore(branchTarget, branchPosition); processor.InsertBefore(branchTarget, processor.Create(OpCodes.Ldarg_0)); processor.InsertBefore(branchTarget, processor.Create(OpCodes.Call, typeInfo.IsInterface ? iinterfaceImplAddressGetter : uobjectAddressGetter)); processor.InsertBefore(branchTarget, processor.Create(OpCodes.Ldstr, method.Name)); processor.InsertBefore(branchTarget, processor.Create(OpCodes.Call, reflectionGetFunctionFromInstance)); processor.InsertBefore(branchTarget, processor.Create(OpCodes.Stfld, functionAddressField)); processor.InsertBefore(branchPosition, processor.Create(OpCodes.Brfalse_S, branchTarget)); } InsertNativeFunctionInvokerIsValidSafeguard(type, functionInfo, method, injectedMembers, processor); // Add an object destroyed check if this isn't a delegate if (!isDelegate) { InsertObjectDestroyedCheck(typeInfo, processor); } }