Beispiel #1
0
        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);
                }
            }
        }