示例#1
0
        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);
            }
        }
示例#2
0
        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);
            }
        }