public override void Emit(IMemberEmitter member, ILGenerator gen) { var local = gen.DeclareLocal(typeof(object[])); gen.Emit(OpCodes.Ldc_I4, args.Length); gen.Emit(OpCodes.Newarr, typeof(object)); gen.Emit(OpCodes.Stloc, local); for (var i = 0; i < args.Length; i++) { gen.Emit(OpCodes.Ldloc, local); gen.Emit(OpCodes.Ldc_I4, i); var reference = args[i]; ArgumentsUtil.EmitLoadOwnerAndReference(reference, gen); if (reference.Type.GetTypeInfo().IsByRef) { throw new NotSupportedException(); } if (reference.Type.GetTypeInfo().IsPointer) { gen.Emit(OpCodes.Call, ArgumentsUtil.IntPtrFromPointer()); gen.Emit(OpCodes.Box, typeof(IntPtr)); } if (reference.Type.GetTypeInfo().IsValueType) { gen.Emit(OpCodes.Box, reference.Type); } else if (reference.Type.GetTypeInfo().IsGenericParameter) { gen.Emit(OpCodes.Box, reference.Type); } gen.Emit(OpCodes.Stelem_Ref); } gen.Emit(OpCodes.Ldloc, local); }
public override void Emit(IMemberEmitter member, ILGenerator gen) { right.Emit(member, gen); if (fromType == target) { return; } if (fromType.IsByRef) { fromType = fromType.GetElementType(); } if (target.IsByRef) { target = target.GetElementType(); } if (target.IsPointer && fromType == typeof(object)) { gen.Emit(OpCodes.Unbox_Any, typeof(IntPtr)); gen.Emit(OpCodes.Call, ArgumentsUtil.PointerFromIntPtr()); } else if (target == typeof(object) && fromType.IsPointer) { gen.Emit(OpCodes.Call, ArgumentsUtil.IntPtrFromPointer()); gen.Emit(OpCodes.Box, typeof(IntPtr)); } else if (target.IsValueType) { if (fromType.IsValueType) { throw new NotImplementedException("Cannot convert between distinct value types"); } else { // Unbox conversion // Assumes fromType is a boxed value // if we can, we emit a box and ldind, otherwise, we will use unbox.any if (LdindOpCodesDictionary.Instance[target] != LdindOpCodesDictionary.EmptyOpCode) { gen.Emit(OpCodes.Unbox, target); OpCodeUtil.EmitLoadIndirectOpCodeForType(gen, target); } else { gen.Emit(OpCodes.Unbox_Any, target); } } } else { if (fromType.IsValueType) { // Box conversion gen.Emit(OpCodes.Box, fromType); EmitCastIfNeeded(typeof(object), target, gen); } else { // Possible down-cast EmitCastIfNeeded(fromType, target, gen); } } }