/// <summary> /// Gets the marshaler methods for a marshaler which has to be instantiated be used (the collection marshalers) /// </summary> private bool GetInstancedMarshalerMethods(ManagedUnrealPropertyInfo propertyInfo, ManagedUnrealMarshalerType marshalerType, out System.Reflection.ConstructorInfo ctor, out System.Reflection.MethodInfo fromNativeMethod, out System.Reflection.MethodInfo toNativeMethod) { Type collectionMarshalerType = ManagedUnrealTypeInfo.GetMarshalerType(marshalerType, propertyInfo); // Find the constructor for the marshaler ctor = null; foreach (System.Reflection.ConstructorInfo ctorInfo in collectionMarshalerType.GetConstructors()) { System.Reflection.ParameterInfo[] ctorParams = ctorInfo.GetParameters(); if (ctorParams.Length > 2 && ctorParams[0].ParameterType == typeof(int) && ctorParams[1].ParameterType == typeof(UFieldAddress)) { ctor = ctorInfo; break; } } fromNativeMethod = GetInstancedMarshalerMethod(collectionMarshalerType, true); toNativeMethod = GetInstancedMarshalerMethod(collectionMarshalerType, false); bool success = ctor != null && fromNativeMethod != null && toNativeMethod != null; if (!success) { throw new RewriteException(propertyInfo.Path, "Failed to get marshaler methods"); } return(success); }
private void WriteNativeFunctionInvoker(TypeDefinition type, ManagedUnrealTypeInfo typeInfo, ManagedUnrealFunctionInfo functionInfo, MethodDefinition method, InjectedMembers injectedMembers, bool perInstanceFunctionAddress) { method.Body = new MethodBody(method); WriteNativeFunctionInvokerBody(type, typeInfo, functionInfo, method, injectedMembers, GetParamsFromMethod(type, functionInfo, method), method.Body.GetILProcessor(), false, perInstanceFunctionAddress); }
private VariableDefinition EmitCreateMarshaler(ILProcessor processor, Instruction loadBuffer, FieldDefinition offsetField, FieldDefinition nativePropertyField, ManagedUnrealPropertyInfo propertyInfo) { VariableDefinition marshalerVar = null; if (ManagedUnrealTypeInfo.PropertyRequiresMarshalerInstance(propertyInfo)) { TypeReference marshalerType = assembly.MainModule.ImportEx(ManagedUnrealTypeInfo.GetMarshalerType(ManagedUnrealMarshalerType.Copy, propertyInfo)); marshalerVar = new VariableDefinition(marshalerType); } if (marshalerVar != null) { processor.Emit(OpCodes.Ldc_I4_1); processor.Emit(OpCodes.Ldsfld, nativePropertyField); // New delegate marshaling code, this will use a cached delegate EmitCachedMarshalingDelegates(processor, propertyInfo, ManagedUnrealMarshalerType.Copy); System.Reflection.ConstructorInfo ctor; System.Reflection.MethodInfo fromNativeMethod; System.Reflection.MethodInfo toNativeMethod; GetInstancedMarshalerMethods(propertyInfo, ManagedUnrealMarshalerType.Copy, out ctor, out fromNativeMethod, out toNativeMethod); processor.Emit(OpCodes.Newobj, assembly.MainModule.ImportEx(ctor)); processor.Emit(OpCodes.Stloc, marshalerVar); } return(marshalerVar); }
private Instruction[] CreateFunctionOutDefaults(ILProcessor processor, ManagedUnrealFunctionInfo functionInfo, MethodDefinition method) { List <Instruction> instructions = new List <Instruction>(); // Set out params to the equivalent of default(XXXX) for (int i = 0; i < functionInfo.Params.Count; ++i) { ManagedUnrealPropertyInfo param = functionInfo.Params[i]; if (param.IsOut) { instructions.AddRange(CreateSetDefaultValue(processor, param.Type.TypeCode, method.Parameters[i])); } } // Add a return var and set it to the equivalent of default(XXXX) if (functionInfo.ReturnProp != null) { TypeReference returnType = assembly.MainModule.ImportEx(ManagedUnrealTypeInfo.GetTypeFromPropertyInfo(functionInfo.ReturnProp)); VariableDefinition returnVar = new VariableDefinition(returnType); method.Body.Variables.Add(returnVar); instructions.AddRange(CreateSetDefaultValue(processor, functionInfo.ReturnProp.Type.TypeCode, returnVar)); instructions.Add(processor.Create(OpCodes.Ldloc, returnVar)); } return(instructions.ToArray()); }
private void RewriteInterface(TypeDefinition type, ManagedUnrealTypeInfo interfaceInfo) { InjectedMembers injectedMembers = new InjectedMembers(interfaceInfo); Dictionary <string, List <MethodDefinition> > methodsByName = new Dictionary <string, List <MethodDefinition> >(); foreach (MethodDefinition method in type.Methods) { List <MethodDefinition> methods; if (!methodsByName.TryGetValue(method.Name, out methods)) { methodsByName.Add(method.Name, methods = new List <MethodDefinition>()); } methods.Add(method); } foreach (ManagedUnrealFunctionInfo functionInfo in interfaceInfo.Functions) { List <MethodDefinition> methods; methodsByName.TryGetValue(functionInfo.Name, out methods); VerifySingleResult(methods, type, "Function " + functionInfo.Name + " (the reflection system doesn't support overloads"); AddPathAttribute(methods[0], functionInfo); } TypeDefinition interfaceImplType = CreateDefaultInterfaceImpl(type, interfaceInfo, methodsByName); AddPathAttribute(type, interfaceInfo, interfaceImplType); }
private void EmitLoad(ILProcessor processor, Instruction loadBuffer, FieldDefinition offsetField, FieldDefinition nativePropertyField, ManagedUnrealTypeInfo typeInfo, ManagedUnrealPropertyInfo propertyInfo, VariableDefinition marshalerVar, ParameterDefinition param) { // This is moving the native buffer into the parameter // If the param is "out" or "ref" load the arg and store it afterwards // NOTE: Is this a redundant check? Why would we be loading the native buffer into a param if it isn't ref / out? // - Collections were treated as a special case. Look into if it is still required. If not; remove this ref/out check // (or just change it to an assert) and only take the ref/out path. bool outOrRef = propertyInfo.IsByRef || propertyInfo.IsOut; if (outOrRef) { System.Diagnostics.Debug.Assert(param.IsOut || param.ParameterType.IsByReference); processor.Emit(OpCodes.Ldarg, param); } EmitLoad(processor, loadBuffer, offsetField, nativePropertyField, typeInfo, propertyInfo, marshalerVar); if (outOrRef) { processor.Append(CreateStRefOutParam(processor, param, propertyInfo.Type.TypeCode)); } else { // Is this useful for anything? Old code used it when not handling ref/out properly. processor.Emit(OpCodes.Starg, param); } }
private void EndSetter(ManagedUnrealTypeInfo typeInfo, ManagedUnrealPropertyInfo propertyInfo, MethodDefinition setter, FieldDefinition isValidField, ILProcessor processor) { processor.Emit(OpCodes.Ret); InsertPropertyIsValidSafeguard(propertyInfo, setter, false, isValidField, processor); InsertObjectDestroyedCheck(typeInfo, processor); setter.Body.OptimizeMacros(); }
private void WriteGetterCollection(ManagedUnrealTypeInfo typeInfo, ManagedUnrealPropertyInfo propertyInfo, MethodDefinition getter, FieldDefinition isValidField, FieldDefinition offsetField, FieldDefinition nativePropertyField, FieldDefinition collectionWrapperField) { ILProcessor processor = BeginGetter(getter); processor.Emit(OpCodes.Ldarg_0); processor.Emit(OpCodes.Ldfld, collectionWrapperField); // Save the position of the branch instruction for later, when we have a reference to its target. // (will insert Brtrue_S before this instruction as a null check on the wrapper field) processor.Emit(OpCodes.Ldarg_0); Instruction branchPosition = processor.Body.Instructions[processor.Body.Instructions.Count - 1]; processor.Emit(OpCodes.Ldc_I4_1); processor.Emit(OpCodes.Ldsfld, nativePropertyField); // New delegate marshaling code, this will use a cached delegate EmitCachedMarshalingDelegates(processor, propertyInfo, ManagedUnrealMarshalerType.Default); System.Reflection.ConstructorInfo collectionCtor; System.Reflection.MethodInfo fromNativeMethod; System.Reflection.MethodInfo toNativeMethod; GetInstancedMarshalerMethods(propertyInfo, ManagedUnrealMarshalerType.Default, out collectionCtor, out fromNativeMethod, out toNativeMethod); int numFromNativeParams = fromNativeMethod.GetParameters().Length; // Create an instance of the collection marshaler and store in the member field processor.Emit(OpCodes.Newobj, assembly.MainModule.ImportEx(collectionCtor)); processor.Emit(OpCodes.Stfld, collectionWrapperField); // Store the branch destination processor.Emit(OpCodes.Ldarg_0); Instruction branchTarget = processor.Body.Instructions[processor.Body.Instructions.Count - 1]; processor.Emit(OpCodes.Ldfld, collectionWrapperField); processor.Emit(OpCodes.Ldarg_0); processor.Emit(OpCodes.Call, uobjectAddressGetter); processor.Emit(OpCodes.Ldsfld, offsetField); processor.Emit(OpCodes.Call, intPtrAddMethod); if (numFromNativeParams == marshalerFromNativeParamCount) { // arrayIndex, prop (IntPtr.Zero as prop is already known by the collection marshaler), this processor.Emit(OpCodes.Ldc_I4_0); processor.Emit(OpCodes.Ldnull); processor.Emit(OpCodes.Ldarg_0); } else { System.Diagnostics.Debug.Assert(numFromNativeParams == marshalerFromNativeParamCountMin); } processor.Emit(OpCodes.Callvirt, assembly.MainModule.ImportEx(fromNativeMethod)); // Now insert the branch Instruction branchInstruction = processor.Create(OpCodes.Brtrue_S, branchTarget); processor.InsertBefore(branchPosition, branchInstruction); EndGetter(typeInfo, propertyInfo, getter, isValidField, processor); }
public override void ProcessClass(ManagedUnrealTypeInfo typeInfo) { typeInfo.AdditionalFlags |= ManagedUnrealTypeInfoFlags.UClass; typeInfo.ClassFlags |= (EClassFlags)Flags; if (!string.IsNullOrEmpty(Config)) { typeInfo.ClassConfigName = Config; } }
private void WriteGetterFixedSizeArray(TypeDefinition type, ManagedUnrealTypeInfo typeInfo, ManagedUnrealPropertyInfo propertyInfo, MethodDefinition getter, FieldDefinition isValidField, FieldDefinition offsetField, FieldDefinition nativePropertyField, FieldDefinition fixedSizeArrayField) { ILProcessor processor = BeginGetter(getter); processor.Emit(OpCodes.Ldarg_0); processor.Emit(OpCodes.Ldfld, fixedSizeArrayField); // Save the position of the branch instruction for later, when we have a reference to its target. // (will insert Brtrue_S before this instruction as a null check on the wrapper field) processor.Emit(OpCodes.Ldarg_0); Instruction branchPosition = processor.Body.Instructions[processor.Body.Instructions.Count - 1]; MethodReference constructor = null; foreach (MethodDefinition ctor in fixedSizeArrayField.FieldType.Resolve().GetConstructors()) { if (ctor.Parameters.Count == 3) { constructor = ctor; break; } } VerifyNonNull(constructor, type, "constructor for " + fixedSizeArrayField.FieldType.FullName); constructor = GetConstrainedGenericTypeCtor(fixedSizeArrayField.FieldType, constructor); // new TFixedSizeArray<XXXX>(IntPtr.Add(Address, XXXX_Offset), XXXX_PropertyAddress, this); // IntPtr.Add(this.Address, XXXX_Offset) processor.Emit(OpCodes.Ldarg_0); processor.Emit(OpCodes.Call, uobjectAddressGetter); processor.Emit(OpCodes.Ldsfld, offsetField); processor.Emit(OpCodes.Call, intPtrAddMethod); // XXXX_PropertyAddress processor.Emit(OpCodes.Ldsfld, nativePropertyField); // this processor.Emit(OpCodes.Ldarg_0); // Create an instance of the array and store in the member field processor.Emit(OpCodes.Newobj, constructor); processor.Emit(OpCodes.Stfld, fixedSizeArrayField); // return XXXX; processor.Emit(OpCodes.Ldarg_0); Instruction branchTarget = processor.Body.Instructions[processor.Body.Instructions.Count - 1]; processor.Emit(OpCodes.Ldfld, fixedSizeArrayField); // Insert the branch (before the return statement) Instruction branchInstruction = processor.Create(OpCodes.Brtrue_S, branchTarget); processor.InsertBefore(branchPosition, branchInstruction); EndGetter(typeInfo, propertyInfo, getter, isValidField, processor); }
public override void ProcessClass(ManagedUnrealTypeInfo typeInfo) { if (Enabled) { typeInfo.ClassFlags |= EClassFlags.EditInlineNew; } else { typeInfo.ClassFlags &= ~EClassFlags.EditInlineNew; } }
public override void ProcessClass(ManagedUnrealTypeInfo typeInfo) { if (IsTransient) { typeInfo.ClassFlags |= EClassFlags.Transient; } else { typeInfo.ClassFlags &= ~EClassFlags.Transient; } }
public override void ProcessClass(ManagedUnrealTypeInfo typeInfo) { if (Collapse) { typeInfo.ClassFlags |= EClassFlags.CollapseCategories; } else { typeInfo.ClassFlags &= ~EClassFlags.CollapseCategories; } }
private void WriteGetter(ManagedUnrealTypeInfo typeInfo, ManagedUnrealPropertyInfo propertyInfo, MethodDefinition getter, FieldDefinition isValidField, FieldDefinition offsetField, FieldDefinition nativePropertyField) { ILProcessor processor = BeginGetter(getter); Instruction[] loadBufferInstructions = GetLoadNativeBufferInstructions(typeInfo, processor, null, offsetField); MethodReference marshaler = GetFromNativeMarshaler(ManagedUnrealMarshalerType.Default, propertyInfo); WriteMarshalFromNative(processor, nativePropertyField, loadBufferInstructions, null, marshaler); EndGetter(typeInfo, propertyInfo, getter, isValidField, processor); }
private void EmitLoad(ILProcessor processor, Instruction loadBuffer, FieldDefinition offsetField, FieldDefinition nativePropertyField, ManagedUnrealTypeInfo typeInfo, ManagedUnrealPropertyInfo propertyInfo, VariableDefinition marshalerVar, FieldDefinition field) { // Assuming we are targeting "this" processor.Emit(OpCodes.Ldarg_0); EmitLoad(processor, loadBuffer, offsetField, nativePropertyField, typeInfo, propertyInfo, marshalerVar); // Assuming we are storing into a non-static field processor.Emit(OpCodes.Stfld, field); }
private void WriteSetter(ManagedUnrealTypeInfo typeInfo, ManagedUnrealPropertyInfo propertyInfo, MethodDefinition setter, FieldDefinition isValidField, FieldDefinition offsetField, FieldDefinition nativePropertyField) { ILProcessor processor = BeginSetter(setter); Instruction loadValue = processor.Create(OpCodes.Ldarg_1); Instruction[] loadBufferInstructions = GetLoadNativeBufferInstructions(typeInfo, processor, null, offsetField); MethodReference marshaler = GetToNativeMarshaler(ManagedUnrealMarshalerType.Default, propertyInfo); WriteMarshalToNative(processor, nativePropertyField, loadBufferInstructions, null, loadValue, marshaler); EndSetter(typeInfo, propertyInfo, setter, isValidField, processor); }
private void WriteCachedFTextGetter(ManagedUnrealTypeInfo typeInfo, ManagedUnrealPropertyInfo propertyInfo, MethodDefinition getter, FieldDefinition isValidField, FieldDefinition offsetField, FieldDefinition cachedFTextField) { ILProcessor processor = BeginGetter(getter); WriteCachedFTextGetterSetter(offsetField, cachedFTextField, processor, new Instruction[] { processor.Create(OpCodes.Ldfld, cachedFTextField) }); EndGetter(typeInfo, propertyInfo, getter, isValidField, processor); }
private FieldDefinition AddNativePropertyField(TypeDefinition type, ManagedUnrealFunctionInfo functionInfo, ManagedUnrealPropertyInfo paramInfo) { if (!ManagedUnrealTypeInfo.RequiresNativePropertyField(paramInfo, codeSettings.LazyFunctionParamInitDestroy)) { return(null); } FieldDefinition field = new FieldDefinition(functionInfo.Name + "_" + paramInfo.Name + codeSettings.VarNames.PropertyAddress, FieldAttributes.Static | FieldAttributes.Private, ufieldAddressTypeRef); type.Fields.Add(field); return(field); }
public override void ProcessClass(ManagedUnrealTypeInfo typeInfo) { if (IsPlacable && typeInfo.ClassFlags.HasFlag(EClassFlags.NotPlaceable)) { InvalidTarget = true; InvalidTargetReason = "The 'placeable' specifier is only allowed on classes which have " + "a base class that's marked as not placeable. Classes are assumed to be placeable by default."; } else if (!IsPlacable) { typeInfo.ClassFlags |= EClassFlags.NotPlaceable; } }
public override void ProcessStruct(ManagedUnrealTypeInfo typeInfo) { typeInfo.StructFlags |= (EStructFlags)Flags; if (ForceBlittable) { typeInfo.BlittableKind = ManagedUnrealBlittableKind.ForceBlittable; } if (Atomic) { typeInfo.StructFlags |= EStructFlags.Atomic; } typeInfo.AdditionalFlags |= ManagedUnrealTypeInfoFlags.UStruct; }
private void EmitFunctionParamDestroy(ILProcessor processor, ManagedUnrealFunctionInfo functionInfo, ManagedUnrealPropertyInfo paramInfo, VariableDefinition paramsBuffer, FieldDefinition nativePropertyField) { if (!codeSettings.LazyFunctionParamInitDestroy && ManagedUnrealTypeInfo.PropertyRequiresDestroy(paramInfo)) { // Ensure the checks to include the native field prop are in sync with this function Debug.Assert(nativePropertyField != null); // NativeReflection.DestroyValue_InContainer(XXXX_YYYY_PropertyAddress.Address, ParamsBuffer) EmitLdNativePropertyFieldAddress(processor, nativePropertyField); processor.Emit(OpCodes.Ldloc, paramsBuffer); processor.Emit(OpCodes.Call, reflectionDestroyValue_InContainer); } }
/// <summary> /// Loads the static delegates FromNative / ToNative from CachedMarshalingDelegates<,> /// e.g. CachedMarshalingDelegates<int, BlittableTypeMarshaler<int>>.FromNative / .ToNative /// </summary> private void EmitCachedMarshalingDelegates(ILProcessor processor, ManagedUnrealPropertyInfo propertyInfo, ManagedUnrealMarshalerType marshalerType) { foreach (ManagedUnrealTypeInfoReference genericArg in propertyInfo.GenericArgs) { Type cachedMarshalingDelegatesType = ManagedUnrealTypeInfo.GetCachedMarshalingDelegatesType(marshalerType, genericArg); FieldReference fromNative = assembly.MainModule.ImportEx( ManagedUnrealTypeInfo.GetCachedMarshalingDelegatesDelegate(cachedMarshalingDelegatesType, true)); FieldReference toNative = assembly.MainModule.ImportEx( ManagedUnrealTypeInfo.GetCachedMarshalingDelegatesDelegate(cachedMarshalingDelegatesType, false)); processor.Emit(OpCodes.Ldsfld, fromNative); processor.Emit(OpCodes.Ldsfld, toNative); } }
private void EmitStore(ILProcessor processor, Instruction loadBuffer, FieldDefinition offsetField, FieldDefinition nativePropertyField, ManagedUnrealTypeInfo typeInfo, ManagedUnrealPropertyInfo propertyInfo, Instruction[] loadValue, VariableDefinition marshalerVar) { if (marshalerVar != null) { processor.Emit(ManagedUnrealTypeInfo.IsPropertyMarshalerStruct(propertyInfo) ? OpCodes.Ldloca : OpCodes.Ldloc, marshalerVar); } Instruction[] loadBufferInstructions = GetLoadNativeBufferInstructions(typeInfo, processor, loadBuffer, offsetField); MethodReference toNativeMethod = GetToNativeMarshaler(ManagedUnrealMarshalerType.Copy, propertyInfo); WriteMarshalToNative(processor, nativePropertyField, loadBufferInstructions, null, loadValue, toNativeMethod); }
private void WriteCachedFTextSetter(ManagedUnrealTypeInfo typeInfo, ManagedUnrealPropertyInfo propertyInfo, MethodDefinition setter, FieldDefinition isValidField, FieldDefinition offsetField, FieldDefinition cachedFTextField) { ILProcessor processor = BeginSetter(setter); WriteCachedFTextGetterSetter(offsetField, cachedFTextField, processor, new Instruction[] { processor.Create(OpCodes.Ldfld, cachedFTextField), processor.Create(OpCodes.Ldarg_1), processor.Create(OpCodes.Callvirt, ftextCopyFrom) }); EndSetter(typeInfo, propertyInfo, setter, isValidField, processor); }
public override void ProcessClass(ManagedUnrealTypeInfo typeInfo) { if (ClassWithinType != null) { if (!ClassWithinType.IsSameOrSubclassOf(typeof(UObject))) { throw new ManagedUnrealTypeInfoException("The base type for ClassWithin is not a UObject type '" + typeInfo.FullName + "'"); } } else if (string.IsNullOrEmpty(Path)) { throw new ManagedUnrealTypeInfoException("Type / path not specified for ClassWithin on '" + typeInfo.FullName + "'"); } throw new NotImplementedException("TODO: Create some way of linking this to UClass " + " if the target is a managed unreal type it wont have a path specified yet - use the fully qualified name?"); }
private Dictionary <ManagedUnrealPropertyInfo, ParameterDefinition> GetParamsFromMethod(TypeDefinition type, ManagedUnrealFunctionInfo functionInfo, MethodDefinition method, InjectedMembers injectedMembers, bool addFields) { Dictionary <ManagedUnrealPropertyInfo, ParameterDefinition> parameters = new Dictionary <ManagedUnrealPropertyInfo, ParameterDefinition>(); foreach (ManagedUnrealPropertyInfo param in functionInfo.Params) { Type paramType = ManagedUnrealTypeInfo.GetTypeFromPropertyInfo(param); List <ParameterDefinition> foundParams = new List <ParameterDefinition>(); foreach (ParameterDefinition paramDef in method.Parameters) { if (paramDef.Name == param.Name) { foundParams.Add(paramDef); break; } } VerifySingleResult(foundParams, type, "Param count mismatch " + param.Name + " in delegate"); if (addFields) { FieldDefinition isValidField = AddIsValidField(type, functionInfo, param); FieldDefinition offsetField = AddOffsetField(type, functionInfo, param); FieldDefinition nativePropertyField = AddNativePropertyField(type, functionInfo, param); injectedMembers.SetFunctionParamIsValid(functionInfo, param, isValidField); injectedMembers.SetFunctionParamOffset(functionInfo, param, offsetField); injectedMembers.SetFunctionParamPropertyAddress(functionInfo, param, nativePropertyField); } parameters.Add(param, foundParams[0]); } if (addFields && functionInfo.ReturnProp != null) { FieldDefinition isValidField = AddIsValidField(type, functionInfo, functionInfo.ReturnProp); FieldDefinition offsetField = AddOffsetField(type, functionInfo, functionInfo.ReturnProp); FieldDefinition nativePropertyField = AddNativePropertyField(type, functionInfo, functionInfo.ReturnProp); injectedMembers.SetFunctionParamIsValid(functionInfo, functionInfo.ReturnProp, isValidField); injectedMembers.SetFunctionParamOffset(functionInfo, functionInfo.ReturnProp, offsetField); injectedMembers.SetFunctionParamPropertyAddress(functionInfo, functionInfo.ReturnProp, nativePropertyField); } return(parameters); }
/// <summary> /// Inserts an IsValid safeguard on the given non-blittable struct marshaling method (ctor (FromNative) / ToNative) /// </summary> private void InsertStructMarshalerIsValidSafeguard(TypeDefinition type, ManagedUnrealTypeInfo structInfo, MethodDefinition method, InjectedMembers injectedMembers, ILProcessor processor, bool isCtor) { if (!codeSettings.GenerateIsValidSafeguards) { return; } FieldDefinition structIsValidField = injectedMembers.StructIsValid; if (structIsValidField == null) { return; } // If the struct isn't valid create a log and set any out params to default values // if (!structName_IsValid) // { // NativeReflection.LogInvalidStructAccessed("XXXX"); // PropXXX = default(XXXX); (constructor only) // return; // } List <Instruction> instructions = new List <Instruction>(); Instruction branchTarget = processor.Body.Instructions[0]; instructions.Add(processor.Create(OpCodes.Ldsfld, structIsValidField)); instructions.Add(processor.Create(OpCodes.Brtrue, branchTarget)); instructions.Add(processor.Create(OpCodes.Ldstr, structInfo.Path)); instructions.Add(processor.Create(OpCodes.Call, reflectionLogInvalidStructAccessedMethod)); if (isCtor) { // Set struct members to default(XXXX) instructions.AddRange(CreateStructPropertyDefaults(processor, structInfo, type)); } instructions.Add(processor.Create(OpCodes.Ret)); // Insert the instructions at the start InsertInstructionsAt(processor, 0, instructions.ToArray()); }
private void WriteGetterDelegate(ManagedUnrealTypeInfo typeInfo, ManagedUnrealPropertyInfo propertyInfo, MethodDefinition getter, FieldDefinition isValidField, FieldDefinition offsetField, FieldDefinition delegateWrapperField) { ILProcessor processor = BeginGetter(getter); processor.Emit(OpCodes.Ldarg_0); processor.Emit(OpCodes.Ldfld, delegateWrapperField); // Save the position of the branch instruction for later, when we have a reference to its target. // (will insert Brtrue_S before this instruction as a null check on the wrapper field) processor.Emit(OpCodes.Ldarg_0); Instruction branchPosition = processor.Body.Instructions[processor.Body.Instructions.Count - 1]; Type delegateType = ManagedUnrealTypeInfo.GetTypeFromPropertyInfo(propertyInfo); // Find the default constructor / SetAddress method for the delegate System.Reflection.ConstructorInfo delegateCtor = delegateType.GetConstructor(Type.EmptyTypes); System.Reflection.MethodInfo setAddressMethod = delegateType.GetMethod("SetAddress"); // Create an instance of the delegate and store in the member field processor.Emit(OpCodes.Newobj, assembly.MainModule.ImportEx(delegateCtor)); processor.Emit(OpCodes.Stfld, delegateWrapperField); processor.Emit(OpCodes.Ldarg_0); processor.Emit(OpCodes.Ldfld, delegateWrapperField); processor.Emit(OpCodes.Ldarg_0); processor.Emit(OpCodes.Call, uobjectAddressGetter); processor.Emit(OpCodes.Ldsfld, offsetField); processor.Emit(OpCodes.Call, intPtrAddMethod); processor.Emit(OpCodes.Callvirt, assembly.MainModule.ImportEx(setAddressMethod)); processor.Emit(OpCodes.Ldarg_0); Instruction branchTarget = processor.Body.Instructions[processor.Body.Instructions.Count - 1]; processor.Emit(OpCodes.Ldfld, delegateWrapperField); // Insert the branch Instruction branchInstruction = processor.Create(OpCodes.Brtrue_S, branchTarget); processor.InsertBefore(branchPosition, branchInstruction); EndGetter(typeInfo, propertyInfo, getter, isValidField, processor); }
private Instruction[] CreateStructPropertyDefaults(ILProcessor processor, ManagedUnrealTypeInfo structInfo, TypeDefinition structType) { List <Instruction> instructions = new List <Instruction>(); Dictionary <string, FieldDefinition> fieldsByName = new Dictionary <string, FieldDefinition>(); foreach (FieldDefinition fieldDef in structType.Fields) { fieldsByName.Add(fieldDef.Name, fieldDef); } foreach (ManagedUnrealPropertyInfo propertyInfo in structInfo.Properties) { FieldDefinition field = null; fieldsByName.TryGetValue(propertyInfo.Name, out field); VerifyNonNull(field, structType, "field " + propertyInfo.Name); instructions.Add(processor.Create(OpCodes.Ldarg_0)); instructions.AddRange(CreateSetDefaultValue(processor, propertyInfo.Type.TypeCode, field)); } return(instructions.ToArray()); }
private void EmitStore(ILProcessor processor, Instruction loadBuffer, FieldDefinition offsetField, FieldDefinition nativePropertyField, ManagedUnrealTypeInfo typeInfo, ManagedUnrealPropertyInfo propertyInfo, VariableDefinition marshalerVar, ParameterDefinition param) { // This is moving the parameter into the native buffer Instruction[] loadValue = null; if (propertyInfo.IsByRef) { // If this is a "ref" param we need to pass the arg without the ref as no marshalers use by ref args. // (if they did support ref we would need to do the opposite on all args which didn't match the ref arg) System.Diagnostics.Debug.Assert(param.ParameterType.IsByReference); loadValue = new Instruction[] { processor.Create(OpCodes.Ldarg, param), CreateLdRefOutParam(processor, param, propertyInfo.Type.TypeCode) }; } else { loadValue = new Instruction[] { processor.Create(OpCodes.Ldarg, param) }; } EmitStore(processor, loadBuffer, offsetField, nativePropertyField, typeInfo, propertyInfo, loadValue, marshalerVar); }