private Func <TypeDefinition[]> DefineClrType(ClangFunctionInfoBase funcInfo) { var funcName = funcInfo.Name; Debug.WriteLine($"Defining function {funcName}"); if (TypeRedirects.TryGetValue(funcName, out var rename)) { funcName = rename; } var funcRef = Module.GetType(funcName, true); var funcDef = funcRef.Resolve(); if (funcDef != null) { return(null); } funcDef = Module.DefineType(funcName, DelegateTypeAttributes, MulticastDelegateType); funcDef.SetCustomAttribute(() => new BinderGeneratedAttribute()); var umfpDef = new TypeDefinition(funcDef.Namespace, funcDef.Name + "Unmanaged", TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit | TypeAttributes.SequentialLayout | TypeAttributes.Public, Module.TypeSystem.ValueType); Module.Types.Add(umfpDef); var umfpRef = Module.ImportReference(umfpDef); var iumfpGtd = IUnmanagedFunctionPointerGtd.MakeGenericInstanceType(funcDef); var iumfpRef = iumfpGtd.Import(Module); umfpDef.AddInterfaceImplementation(iumfpRef); // todo: add implicit conversion ops using Marshal var retParam = ResolveParameter(funcInfo.ReturnType); /* todo: figure out why the attribute is jacked up * if (!CallingConventionMap.TryGetValue(funcInfo.CallConvention, out var callConv)) * throw new NotImplementedException(); * if (!ClrCallingConventionAttributeMap.TryGetValue(callConv, out var callConvAttr)) * throw new NotImplementedException(); */ var argParams = new LinkedList <ParameterInfo>(funcInfo.Parameters.Select(p => ResolveParameter(p.Type, p.Name, (int)p.Index))); return(() => { retParam.Complete(TypeRedirects, true); var retType = retParam.Type; foreach (var argParam in argParams) { argParam.Complete(TypeRedirects, true); } Debug.WriteLine($"Completed dependencies for function {funcName}"); var umfpValue = umfpDef.DefineField("Value", Module.TypeSystem.IntPtr, FieldAttributes.Public | FieldAttributes.InitOnly); var umfpValueRef = Module.ImportReference(umfpValue); var getDelegateForFpMethodDef = Module.ImportReference( new GenericInstanceMethod(GetDelegateForFpMethodGtd) { GenericArguments = { funcDef } }); var getFpForDelegateMethodDef = Module.ImportReference( new GenericInstanceMethod(GetFpForDelegateMethodGtd) { GenericArguments = { funcDef } }); var umfpDlgt = umfpDef.DefineMethod("op_Implicit", PublicStaticMethodAttributes | MethodAttributes.SpecialName, funcDef, umfpRef); umfpDlgt.GenerateIL(il => { il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, umfpValueRef); il.Emit(OpCodes.Call, getDelegateForFpMethodDef); il.Emit(OpCodes.Ret); }); var dlgtUmfp = umfpDef.DefineMethod("op_Implicit", PublicStaticMethodAttributes | MethodAttributes.SpecialName, umfpRef, funcDef); var dlgtUmfpV0 = new VariableDefinition(umfpRef); dlgtUmfp.Body.Variables.Add(dlgtUmfpV0); dlgtUmfp.Body.InitLocals = true; dlgtUmfp.GenerateIL(il => { il.Emit(OpCodes.Ldloca_S, dlgtUmfpV0); il.Emit(OpCodes.Initobj, umfpRef); il.Emit(OpCodes.Ldloca_S, dlgtUmfpV0); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Call, getFpForDelegateMethodDef); il.Emit(OpCodes.Stfld, umfpValueRef); il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Ret); }); var umfpPtr = umfpDef.DefineMethod("op_Implicit", PublicStaticMethodAttributes | MethodAttributes.SpecialName, Module.TypeSystem.IntPtr, umfpRef); umfpPtr.GenerateIL(il => { il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, umfpValueRef); il.Emit(OpCodes.Ret); }); var ptrUmfp = umfpDef.DefineMethod("op_Implicit", PublicStaticMethodAttributes | MethodAttributes.SpecialName, umfpRef, Module.TypeSystem.IntPtr); var ptrUmfpV0 = new VariableDefinition(umfpRef); ptrUmfp.Body.Variables.Add(ptrUmfpV0); ptrUmfp.Body.InitLocals = true; ptrUmfp.GenerateIL(il => { var argNull = default(CecilLabel); if (EmitNullChecks) { argNull = il.DefineLabel(); } il.Emit(OpCodes.Ldloca_S, ptrUmfpV0); il.Emit(OpCodes.Initobj, umfpRef); il.Emit(OpCodes.Ldloca_S, ptrUmfpV0); il.Emit(OpCodes.Ldarg_0); if (EmitNullChecks) { il.Emit(OpCodes.Dup); il.Emit(OpCodes.Brfalse, argNull); } il.Emit(OpCodes.Stfld, umfpValueRef); il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Ret); if (EmitNullChecks) { il.MarkLabel(argNull); il.Emit(OpCodes.Newobj, ArgumentNullCtor); il.Emit(OpCodes.Throw); // ReSharper disable once PossibleNullReferenceException argNull.Cleanup(); } }); var argTypes = argParams.Select(p => p.Type).ToArray(); var retTypeDef = retType.Resolve(); if (retTypeDef.BaseType != null && retTypeDef.BaseType.Is(MulticastDelegateType)) { // todo: marshalas umfp marshaller var ufpSpecTypeRef = Module.GetType(retTypeDef.FullName + "Unmanaged"); Debug.Assert(ufpSpecTypeRef != null); retType = ufpSpecTypeRef; } for (var i = 0; i < argTypes.Length; i++) { var argType = argTypes[i]; var argTypeDef = argType.Resolve(); if (argType.IsPointer) { var interiorArgType = argType.GetInteriorType(out var transforms); if (interiorArgType.Resolve().IsInterface) { if (!argType.Name.StartsWith("I")) { throw new NotImplementedException(); } var argTypeNameBase = interiorArgType.Name.Substring(1); if (!MarshallableSplitPointers.TryGetValue(argTypeNameBase, out var marshallable)) { TypeReference splitPtrTypeRef; if (_splitPointerDefs.TryGetValue(interiorArgType.FullName, out var splitPtrType)) { splitPtrTypeRef = splitPtrType; } else { var argType32 = Module.GetType(interiorArgType.Namespace, argTypeNameBase + "32"); Debug.Assert(argType32 != null); var argType64 = Module.GetType(interiorArgType.Namespace, argTypeNameBase + "64"); Debug.Assert(argType64 != null); splitPtrType = SplitPointerGtd.MakeGenericInstanceType(interiorArgType, argType32, argType64); if (!_splitPointerDefs.TryAdd(interiorArgType.FullName, splitPtrType)) { throw new NotImplementedException(); } splitPtrTypeRef = splitPtrType.Import(Module); } marshallable = Module.DefineType(argTypeNameBase + "Ptr", PublicSealedStructTypeAttributes); var valueField = marshallable.DefineField("Value", splitPtrTypeRef, FieldAttributes.Public | FieldAttributes.InitOnly); // implicit conversion from split pointer to marshallable for use as params var asSplitPtrOp = marshallable.DefineMethod("op_Implicit", PublicStaticMethodAttributes | MethodAttributes.SpecialName, splitPtrTypeRef, marshallable); asSplitPtrOp.GenerateIL(il => { il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, valueField); il.Emit(OpCodes.Ret); }); // implicit conversion from marshallable to split pointer for use as returns var toSplitPtrOp = marshallable.DefineMethod("op_Implicit", PublicStaticMethodAttributes | MethodAttributes.SpecialName, marshallable, splitPtrTypeRef); var toSplitPtrOpV0 = new VariableDefinition(marshallable); toSplitPtrOp.Body.Variables.Add(toSplitPtrOpV0); toSplitPtrOp.Body.InitLocals = true; toSplitPtrOp.GenerateIL(il => { il.Emit(OpCodes.Ldloca_S, ptrUmfpV0); il.Emit(OpCodes.Initobj, marshallable); il.Emit(OpCodes.Ldloca_S, ptrUmfpV0); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Stfld, valueField); il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Ret); }); if (!MarshallableSplitPointers.TryAdd(argTypeNameBase, marshallable)) { throw new NotImplementedException(); } } Debug.Assert(marshallable != null); argTypes[i] = marshallable.Import(Module) .ApplyTransforms(transforms.Skip(1)); continue; } } if (argTypeDef.BaseType == null) { continue; } if (!argTypeDef.BaseType.Is(MulticastDelegateType)) { continue; } // todo: marshalas umfp marshaller var ufpSpecTypeRef = Module.GetType(argTypeDef.FullName + "Unmanaged"); Debug.Assert(ufpSpecTypeRef != null); argTypes[i] = ufpSpecTypeRef; } try { var ctor = funcDef.DefineConstructor(DelegateConstructorAttributes, Module.TypeSystem.Object, Module.TypeSystem.IntPtr); ctor.SetImplementationFlags(MethodImplAttributes.CodeTypeMask); var method = funcDef.DefineMethod("Invoke", DelegateInvokeMethodAttributes, retType, argTypes); method.SetImplementationFlags(MethodImplAttributes.CodeTypeMask); // todo: figure out why the attribute is jacked up //method.SetCustomAttribute(callConvAttr); argParams.ConsumeLinkedList((argParam, i) => { var param = method.DefineParameter(i + 1, argParam.Attributes, argParam.Name); }); return new[] { funcDef.CreateType() }; } catch (Exception ex) { throw new InvalidProgramException("Critical function type definition failure.", ex); } }); }
private void BuildInterfaceByRefAccessor( TypeDefinition interfaceDef, string propName, ConcurrentDictionary <string, GenericInstanceType> splitPointerDefs, LinkedListNode <ParameterInfo> fieldInfo32, LinkedListNode <ParameterInfo> fieldInfo64, out PropertyDefinition interfacePropDef, out MethodDefinition interfaceMethodDef ) { var module = interfaceDef.Module; var fieldType32 = fieldInfo32.Value.Type; var fieldType64 = fieldInfo64.Value.Type; interfacePropDef = null; interfaceMethodDef = null; var intType = Module.TypeSystem.Int32; var longType = Module.TypeSystem.Int64; if (fieldType32.Is(intType) && fieldType64.Is(longType)) { // IntPtr var propType = Module.TypeSystem.IntPtr; var propRefType = propType.MakeByReferenceType(); interfacePropDef = DefineInterfaceGetProperty(interfaceDef, propRefType, propName); return; } var uIntType = Module.TypeSystem.UInt32; var uLongType = Module.TypeSystem.UInt64; if (fieldType32.Is(uIntType) && fieldType64.Is(uLongType)) { // UIntPtr var propType = Module.TypeSystem.UIntPtr; var propRefType = propType.MakeByReferenceType(); interfacePropDef = DefineInterfaceGetProperty(interfaceDef, propRefType, propName); return; } if (fieldType32.Is(fieldType64) && fieldType32.IsDirect()) { // same type var propType = fieldType32; var propRefType = propType.MakeByReferenceType(); interfacePropDef = DefineInterfaceGetProperty(interfaceDef, propRefType, propName); return; } var fieldElemType32 = fieldType32.GetTypePointedTo(out LinkedList <CecilExtensions.TypeReferenceTransform> transforms32); var fieldElemType64 = fieldType64.GetTypePointedTo(out LinkedList <CecilExtensions.TypeReferenceTransform> transforms64); var pointerDepth32 = transforms32.Count; var pointerDepth64 = transforms64.Count; if (Math.Abs(pointerDepth32 - pointerDepth64) > 1) { throw new NotSupportedException(); } if (fieldType32.IsPointer && fieldType64.Is(intType)) { // 32-bit handle var handleType = HandleInt32Gtd.MakeGenericInstanceType(fieldElemType32); fieldInfo32.Value.Type = handleType; fieldInfo64.Value.Type = handleType; interfacePropDef = DefineInterfaceGetHandleProperty(interfaceDef, handleType, propName); return; } if (fieldType32.IsPointer && fieldType64.Is(uIntType)) { // 32-bit handle var handleType = HandleUInt32Gtd.MakeGenericInstanceType(fieldElemType32); fieldInfo32.Value.Type = handleType; fieldInfo64.Value.Type = handleType; interfacePropDef = DefineInterfaceGetHandleProperty(interfaceDef, handleType, propName); return; } if (fieldType32.Is(longType) && fieldType64.IsPointer) { // 64-bit handle var handleType = HandleInt64Gtd.MakeGenericInstanceType(fieldElemType64); fieldInfo32.Value.Type = handleType; fieldInfo64.Value.Type = handleType; interfacePropDef = DefineInterfaceGetHandleProperty(interfaceDef, handleType, propName); return; } if (fieldType32.Is(uLongType) && fieldType64.IsPointer) { // 64-bit handle var handleType = HandleUInt64Gtd.MakeGenericInstanceType(fieldElemType64); fieldInfo32.Value.Type = handleType; fieldInfo64.Value.Type = handleType; interfacePropDef = DefineInterfaceGetHandleProperty(interfaceDef, handleType, propName); return; } if (fieldElemType64.Is(intType) && IsHandleType(fieldElemType32)) { // 32-bit handle TypeReference handleType = HandleInt32Gtd.MakeGenericInstanceType(fieldElemType32); var updatedFieldType32 = handleType; foreach (var transform in transforms32) { transform(ref updatedFieldType32); } fieldInfo32.Value.Type = updatedFieldType32; var updatedFieldType64 = handleType; foreach (var transform in transforms64) { transform(ref updatedFieldType64); } fieldInfo64.Value.Type = updatedFieldType64; interfacePropDef = DefineInterfaceGetHandleProperty(interfaceDef, handleType, propName, transforms32.Skip(1)); return; } if (fieldElemType64.Is(uIntType) && IsHandleType(fieldElemType32)) { // 32-bit handle TypeReference handleType = HandleUInt32Gtd.MakeGenericInstanceType(fieldElemType32); var updatedFieldType32 = handleType; foreach (var transform in transforms32) { transform(ref updatedFieldType32); } fieldInfo32.Value.Type = updatedFieldType32; var updatedFieldType64 = handleType; foreach (var transform in transforms64) { transform(ref updatedFieldType64); } fieldInfo64.Value.Type = updatedFieldType64; interfacePropDef = DefineInterfaceGetHandleProperty(interfaceDef, handleType, propName, transforms32.Skip(1)); return; } if (fieldElemType32.Is(longType) && IsHandleType(fieldElemType64)) { // 64-bit handle TypeReference handleType = HandleInt64Gtd.MakeGenericInstanceType(fieldElemType64); var updatedFieldType32 = handleType; foreach (var transform in transforms32) { transform(ref updatedFieldType32); } fieldInfo32.Value.Type = updatedFieldType32; var updatedFieldType64 = handleType; foreach (var transform in transforms64) { transform(ref updatedFieldType64); } fieldInfo32.Value.Type = updatedFieldType32; interfacePropDef = DefineInterfaceGetHandleProperty(interfaceDef, handleType, propName, transforms64.Skip(1)); return; } if (fieldElemType32.Is(uLongType) && IsHandleType(fieldElemType64)) { // 64-bit handle TypeReference handleType = HandleUInt64Gtd.MakeGenericInstanceType(fieldElemType64); var updatedFieldType32 = handleType; foreach (var transform in transforms32) { transform(ref updatedFieldType32); } fieldInfo32.Value.Type = updatedFieldType32; var updatedFieldType64 = handleType; foreach (var transform in transforms64) { transform(ref updatedFieldType64); } fieldInfo32.Value.Type = updatedFieldType32; interfacePropDef = DefineInterfaceGetHandleProperty(interfaceDef, handleType, propName, transforms64.Skip(1)); return; } if (fieldType32.IsPointer && fieldType64.IsPointer && fieldElemType32.Is(fieldElemType64)) { if (fieldElemType32.SizeOf() == 0) { throw new NotImplementedException(); } TypeReference propRefType = fieldElemType32; foreach (var transform in transforms32) { transform(ref propRefType); } propRefType = propRefType.MakeByReferenceType(); interfacePropDef = DefineInterfaceGetProperty(interfaceDef, propRefType, propName); return; } var interiorType32 = fieldElemType32.FindInteriorType(ref transforms32); var interiorType64 = fieldElemType64.FindInteriorType(ref transforms64); if (!transforms32.SequenceEqual(transforms64)) { throw new NotImplementedException(); } if (fieldType32.Is(fieldType64) && fieldType32.IsArray) { // ref index implementation if (interiorType32.SizeOf() == 0) { throw new NotImplementedException(); } var fieldElemType = fieldType64.DescendElementType(); if (IsHandleType(interiorType64)) { var handleType = HandleUIntPtrGtd.MakeGenericInstanceType(interiorType64); TypeReference handleElemType = handleType; foreach (var transform in transforms64.Take(transforms64.Count - 2)) { transform(ref handleElemType); } var handleElemRefType = handleElemType.MakeByReferenceType(); interfaceMethodDef = DefineInterfaceGetByIndexMethod(interfaceDef, handleElemRefType, propName); return; } var propElemRefType = fieldElemType.MakeByReferenceType(); interfaceMethodDef = DefineInterfaceGetByIndexMethod(interfaceDef, propElemRefType, propName); return; } if (fieldType32.IsArray || fieldType64.IsArray) { // TODO: ... throw new NotImplementedException(); } var fieldInterfaces32 = interiorType32.GetInterfaces(); var fieldInterfaces64 = interiorType64.GetInterfaces(); var commonInterfaces = fieldInterfaces32.Intersect(fieldInterfaces64).ToArray(); if (commonInterfaces.Length == 0) { // object, boxing reference throw new NotImplementedException(); //DefineInterfaceGetSetProperty(interfaceDef, propType, propName); } if (commonInterfaces.Length > 1) { // TODO: multiple common interface, boxing reference throw new NotImplementedException(); } /* commonInterfaces.Length == 1 */ if (transforms32.First() == CecilExtensions.MakePointerType) { // common interface, boxing reference var commonInterface = commonInterfaces.First(); splitPointerDefs.TryGetValue(commonInterface.FullName, out var splitPointerDef); var propType = splitPointerDef ?? SplitPointerGtd.MakeGenericInstanceType(commonInterface, interiorType32, interiorType64).Import(module); foreach (var transform in transforms32.Skip(1)) { transform(ref propType); } var propRefType = propType.MakeByReferenceType(); interfacePropDef = DefineInterfaceGetProperty(interfaceDef, propRefType, propName); return; } throw new NotImplementedException(); }
private Func <TypeDefinition[]> DefineClrStructInternal(ClangStructInfo structInfo32, ClangStructInfo structInfo64) { if (structInfo32.Size == 0 && structInfo64.Size == 0) { return(DefineClrHandleStructInternal(structInfo64)); } var structName = structInfo32.Name; Debug.WriteLine($"Defining interface and structure {structName}"); if (TypeRedirects.TryGetValue(structName, out var rename)) { structName = rename; } var interfaceName = "I" + structName; if (Module.GetType(interfaceName)?.Resolve() != null) { return(null); } var interfaceDef = Module.DefineType(interfaceName, PublicInterfaceTypeAttributes); interfaceDef.SetCustomAttribute(() => new BinderGeneratedAttribute()); var structDef32 = Module.DefineType(structName + "32", PublicSealedStructTypeAttributes, null, (int)structInfo32.Alignment, (int)structInfo32.Size); structDef32.SetCustomAttribute(() => new BinderGeneratedAttribute()); /* * structDef32.SetCustomAttribute(AttributeInfo.Create( * () => new StructLayoutAttribute(LayoutKind.Sequential) { * Pack = (int) structInfo32.Alignment, * Size = (int) structInfo32.Size * })); */ var structDef64 = Module.DefineType(structName + "64", PublicSealedStructTypeAttributes, null, (int)structInfo64.Alignment, (int)structInfo64.Size); structDef64.SetCustomAttribute(() => new BinderGeneratedAttribute()); /* * structDef64.SetCustomAttribute(AttributeInfo.Create( * () => new StructLayoutAttribute(LayoutKind.Sequential) { * Pack = (int) structInfo64.Alignment, * Size = (int) structInfo64.Size * })); */ _splitPointerDefs[interfaceDef.FullName] = SplitPointerGtd .MakeGenericInstanceType(interfaceDef, structDef32, structDef64); if (!structDef32.Interfaces.Contains(interfaceDef)) { structDef32.AddInterfaceImplementation(interfaceDef); } if (!structDef64.Interfaces.Contains(interfaceDef)) { structDef64.AddInterfaceImplementation(interfaceDef); } var interfacePropDefs = new ConcurrentDictionary <string, PropertyDefinition>(); var interfaceMethodDefs = new ConcurrentDictionary <string, MethodDefinition>(); var fieldParams32 = new LinkedList <ParameterInfo>( structInfo32.Fields.Select(f => ResolveField(f.Type, f.Name, (int)f.Offset))); var fieldParams64 = new LinkedList <ParameterInfo>( structInfo64.Fields.Select(f => ResolveField(f.Type, f.Name, (int)f.Offset))); var interfacePropNames = new LinkedList <string>(structInfo32.Fields .Select(f => f.Name) .Union(structInfo64.Fields .Select(f => f.Name))); TypeDefinition[] BuildInterfacePropsAndStructFields() { foreach (var fieldParam in fieldParams32) { fieldParam.Complete(TypeRedirects, "32"); } foreach (var fieldParam in fieldParams64) { fieldParam.Complete(TypeRedirects, "64"); } Debug.WriteLine($"Completed dependencies for interface and structure {structName}"); interfacePropNames.ConsumeLinkedList(propName => { BuildInterfaceByRefAccessor(interfaceDef, propName, _splitPointerDefs, fieldParams32.Nodes().First(f => f.Value.Name == propName), fieldParams64.Nodes().First(f => f.Value.Name == propName), out var interfacePropDef, out var interfaceMethodDef); if (interfacePropDef != null) { interfacePropDefs[propName] = interfacePropDef; } if (interfaceMethodDef != null) { interfaceMethodDefs[propName] = interfaceMethodDef; } }); var interfaceType = interfaceDef.IsCreated() ? Module.GetType(interfaceDef.FullName) : interfaceDef.CreateType(); /* * if (!structDef32.ImplementedInterfaces.Contains(interfaceType)) * structDef32.AddInterfaceImplementation(interfaceType); * if (!structDef64.ImplementedInterfaces.Contains(interfaceType)) * structDef64.AddInterfaceImplementation(interfaceType); */ void BuildStructField(ParameterInfo fieldParam, TypeDefinition structDef, int bits) { var ptrSizeForType = bits / 8; var fieldName = fieldParam.Name; var fieldType = fieldParam.Type; var isArray = fieldType.IsArray; // never define an array element on a struct // there should be a fixed buffer attribute on the field if (isArray) { fieldType = fieldType.DescendElementType(); } var fieldDef = PrepareAndDefineField( structDef, isArray, fieldParam, ref fieldType, out var fieldInteriorType, out var fieldTransforms); TypeReference fieldRefType; if (isArray) { fieldRefType = fieldType.MakeByReferenceType(); var intfMethodInfo = interfaceType.GetMethod(fieldName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); TypeReference intfMethodType; try { intfMethodType = intfMethodInfo.ReturnType; } catch { intfMethodType = interfaceMethodDefs[fieldName].ReturnType; } var intfMethodElemType = intfMethodType.DescendElementType(); var intfMethodInteriorType = intfMethodType.GetInteriorType(out var methodRetTransforms); if (fieldRefType.Is(intfMethodType) || fieldType.IsPointer && intfMethodElemType.IsPointer || IsIntPtrOrUIntPtr(intfMethodElemType) && fieldType.SizeOf(ptrSizeForType) == ptrSizeForType || IsTypedHandle(intfMethodElemType, fieldType) || fieldInteriorType.Is(intfMethodInteriorType) && fieldTransforms.SequenceEqual(methodRetTransforms.Skip(1))) { //var fixedBufAttrInfo = fieldParam.AttributeInfos.First(ai => ai.Type == FixedBufferAttributeType); var fixedBufSize = fieldParam.ArraySize; var structGetter = structDef.DefineMethod(fieldName, PublicInterfaceImplementationMethodAttributes, intfMethodType, Module.TypeSystem.Int32); structDef.DefineMethodOverride(structGetter, intfMethodInfo); structGetter.DefineParameter(1, ParameterAttributes.In, "index"); SetMethodInliningAttributes(structGetter); structGetter.GenerateIL(il => { var argOutOfRange = default(CecilLabel); if (EmitBoundsChecks) { argOutOfRange = il.DefineLabel(); il.Emit(OpCodes.Ldarg_1); // index il.EmitPushConst(0); // underflow il.Emit(OpCodes.Blt, argOutOfRange); il.Emit(OpCodes.Ldarg_1); // index il.EmitPushConst(fixedBufSize); // overflow il.Emit(OpCodes.Bge, argOutOfRange); } il.Emit(OpCodes.Ldarg_0); // this il.Emit(OpCodes.Ldflda, fieldDef); il.Emit(OpCodes.Ldarg_1); // index il.Emit(OpCodes.Sizeof, fieldType); il.Emit(OpCodes.Mul); il.Emit(OpCodes.Add); if (intfMethodType.Resolve().IsInterface) { il.Emit(OpCodes.Box, fieldType); } il.Emit(OpCodes.Ret); if (EmitBoundsChecks) { il.MarkLabel(argOutOfRange); il.Emit(OpCodes.Newobj, ArgumentOutOfRangeCtor); il.Emit(OpCodes.Throw); // ReSharper disable once PossibleNullReferenceException argOutOfRange.Cleanup(); } }); return; } throw new NotImplementedException(); } fieldRefType = fieldType.MakeByReferenceType(); var propInfo = interfaceType.GetProperty(fieldName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); if (propInfo == null) { throw new NotImplementedException(); } TypeReference propType; try { propType = propInfo.PropertyType; } catch { propType = interfacePropDefs[fieldName].PropertyType; } var propInteriorType = propType.GetInteriorType(out var propTransforms).Resolve(); if (propInteriorType == null) { throw new NotImplementedException(); } var propElemType = propType.DescendElementType(); if (fieldRefType.Is(propType) || fieldType.IsPointer && propElemType.IsPointer || IsIntPtrOrUIntPtr(propElemType) && fieldType.SizeOf(ptrSizeForType) == ptrSizeForType || IsTypedHandle(propElemType, fieldType) || fieldInteriorType.Is(propInteriorType) && fieldTransforms.SequenceEqual(propTransforms.Skip(1))) { /* * var structProp = structDef.DefineProperty(fieldName, * PropertyAttributes.SpecialName, * propType, Type.EmptyTypes); */ var structGetter = structDef.DefineMethod("get_" + fieldName, HiddenPropertyMethodAttributes | MethodAttributes.Virtual, propType); SetMethodInliningAttributes(structGetter); //structProp.SetGetMethod(structGetter); structDef.DefineMethodOverride(structGetter, propInfo.Resolve().GetMethod); structGetter.GenerateIL(il => { il.Emit(OpCodes.Ldarg_0); // this il.Emit(OpCodes.Ldflda, fieldDef); if (propInteriorType.IsInterface) { il.Emit(OpCodes.Box, fieldType); } il.Emit(OpCodes.Ret); }); return; } if (propType.Is(Module.TypeSystem.Object)) { // TODO: boxing reference throw new NotImplementedException(); } if (propType.IsAssignableFrom(fieldType)) { // TODO: boxed interface throw new NotImplementedException(); } throw new NotImplementedException(); } fieldParams32.ConsumeLinkedList(fieldParam => BuildStructField(fieldParam, structDef32, 32)); var structType32 = structDef32; fieldParams64.ConsumeLinkedList(fieldParam => BuildStructField(fieldParam, structDef64, 64)); var structType64 = structDef64; return(new[] { interfaceType, structType32, structType64 }); } return(BuildInterfacePropsAndStructFields); }