Пример #1
0
        void CallInstructionTranslator()
        {
            switch (cilOp)
            {
            case Code.Nop:
            case Code.Volatile:
            case Code.Constrained:
            case Code.Unaligned:
            case Code.Readonly:
            case Code.Tail:

                code.NewInstruction(0x00 /* nop */, null, null);
                break;

            case Code.Break:

                code.NewInstruction(0xCA /* debugger break */, null, null);
                break;

            case Code.Pop:
            case Code.Dup:

                PopOrDupStack(cilOp);
                break;

            case Code.Ldarg_0:
            case Code.Ldarg_1:
            case Code.Ldarg_2:
            case Code.Ldarg_3:
            case Code.Ldloc_0:
            case Code.Ldloc_1:
            case Code.Ldloc_2:
            case Code.Ldloc_3:
            case Code.Ldarg:
            case Code.Ldarg_S:
            case Code.Ldloc:
            case Code.Ldloc_S:

                locals.LoadValue(cilOp, cilInst.Operand);
                break;

            case Code.Stloc_0:
            case Code.Stloc_1:
            case Code.Stloc_2:
            case Code.Stloc_3:
            case Code.Starg:
            case Code.Starg_S:
            case Code.Stloc:
            case Code.Stloc_S:

                locals.StoreValue(cilOp, cilInst.Operand);
                break;

            case Code.Ldarga:
            case Code.Ldloca:
            case Code.Ldarga_S:
            case Code.Ldloca_S:

                locals.LoadAddress(cilInst.Operand);
                break;

            case Code.Ldc_I4_M1:
            case Code.Ldc_I4_0:
            case Code.Ldc_I4_1:
            case Code.Ldc_I4_2:
            case Code.Ldc_I4_3:
            case Code.Ldc_I4_4:
            case Code.Ldc_I4_5:
            case Code.Ldc_I4_6:
            case Code.Ldc_I4_7:
            case Code.Ldc_I4_8:
            case Code.Ldc_I4_S:
            case Code.Ldc_I4:
            case Code.Ldc_I8:
            case Code.Ldc_R4:
            case Code.Ldc_R8:
            case Code.Ldstr:
            case Code.Ldnull:

                LoadConstant(cilOp, cilInst);
                break;

            case Code.Ldfld:
            case Code.Ldflda:
            case Code.Stfld:
            case Code.Ldsfld:
            case Code.Ldsflda:
            case Code.Stsfld:

                LoadStoreField(cilOp, cilInst.Operand);
                break;

            case Code.Initobj:

                InitObject(cilInst.Operand);
                break;

            case Code.Newobj:
            case Code.Call:
            case Code.Callvirt:
            case Code.Ret:

                CallMethod(cilOp, cilInst.Operand);
                break;

            case Code.Castclass:

                CastToClass(cilInst.Operand);
                break;

            case Code.Ldtoken:

                LoadToken();
                break;

            case Code.Unbox:
            case Code.Unbox_Any:

                UnboxObject(cilOp, cilInst.Operand);
                break;

            case Code.Ldobj:
            case Code.Box:

                LoadObject(cilOp, cilInst.Operand);
                break;

            case Code.Stobj:

                StoreObject(cilInst.Operand);
                break;

            case Code.Br:
            case Code.Br_S:
            case Code.Brtrue:
            case Code.Brtrue_S:
            case Code.Beq:
            case Code.Beq_S:
            case Code.Bgt:
            case Code.Bgt_S:
            case Code.Bgt_Un:
            case Code.Bgt_Un_S:
            case Code.Blt:
            case Code.Blt_S:
            case Code.Blt_Un:
            case Code.Blt_Un_S:

                CodeCompare.Straight(code, cilOp, locals, cilInst);
                break;

            case Code.Brfalse:
            case Code.Brfalse_S:
            case Code.Bne_Un:
            case Code.Bne_Un_S:
            case Code.Ble:
            case Code.Ble_S:
            case Code.Ble_Un:
            case Code.Ble_Un_S:
            case Code.Bge:
            case Code.Bge_S:
            case Code.Bge_Un:
            case Code.Bge_Un_S:

                CodeCompare.Opposite(code, cilOp, locals, cilInst);
                break;

            case Code.Cgt:
            case Code.Cgt_Un:
            case Code.Ceq:
            case Code.Clt:
            case Code.Clt_Un:

                CodeCompare.Compare(code, cilOp, cilInst);
                break;

            case Code.Switch:

                CodeCompare.Switch(code, cilInst);
                break;

            case Code.Isinst:

                CodeCompare.Instance(code, locals, cilInst);
                break;

            case Code.Conv_I1:
            case Code.Conv_Ovf_I1:
            case Code.Conv_Ovf_I1_Un:
            case Code.Conv_I2:
            case Code.Conv_Ovf_I2:
            case Code.Conv_Ovf_U2_Un:
            case Code.Conv_I4:
            case Code.Conv_Ovf_I4:
            case Code.Conv_Ovf_I4_Un:
            case Code.Conv_I8:
            case Code.Conv_Ovf_I8:
            case Code.Conv_Ovf_I8_Un:
            case Code.Conv_U1:
            case Code.Conv_Ovf_U1:
            case Code.Conv_Ovf_U1_Un:
            case Code.Conv_U2:
            case Code.Conv_Ovf_U2:
            case Code.Conv_Ovf_I2_Un:
            case Code.Conv_U4:
            case Code.Conv_Ovf_U4:
            case Code.Conv_Ovf_U4_Un:
            case Code.Conv_U8:
            case Code.Conv_Ovf_U8:
            case Code.Conv_Ovf_U8_Un:
            case Code.Conv_I:
            case Code.Conv_Ovf_I:
            case Code.Conv_Ovf_I_Un:
            case Code.Conv_U:
            case Code.Conv_Ovf_U:
            case Code.Conv_Ovf_U_Un:
            case Code.Conv_R4:
            case Code.Conv_R8:
            case Code.Conv_R_Un:

                CodeNumber.Conversion(code, cilOp, cilInst);
                break;

            case Code.Add:
            case Code.Sub:
            case Code.Mul:
            case Code.Neg:
            case Code.Div:
            case Code.Div_Un:
            case Code.Rem:
            case Code.Rem_Un:
            case Code.And:
            case Code.Or:
            case Code.Xor:
            case Code.Not:
            case Code.Shl:
            case Code.Shr:
            case Code.Shr_Un:
            case Code.Add_Ovf:
            case Code.Add_Ovf_Un:
            case Code.Sub_Ovf:
            case Code.Sub_Ovf_Un:
            case Code.Mul_Ovf:
            case Code.Mul_Ovf_Un:

                CodeNumber.Calculation(code, cilOp, cilInst);
                break;

            case Code.Ldind_I1:
            case Code.Ldind_U1:
            case Code.Ldind_I2:
            case Code.Ldind_U2:
            case Code.Ldind_I4:
            case Code.Ldind_U4:
            case Code.Ldind_I8:
            case Code.Ldind_I:
            case Code.Ldind_R4:
            case Code.Ldind_R8:
            case Code.Ldind_Ref:
            case Code.Stind_I1:
            case Code.Stind_I2:
            case Code.Stind_I4:
            case Code.Stind_I8:
            case Code.Stind_I:
            case Code.Stind_R4:
            case Code.Stind_R8:
            case Code.Stind_Ref:

                CodeNumber.Indirection(code, cilOp);
                break;

            case Code.Throw:
            case Code.Rethrow:
            case Code.Leave:
            case Code.Leave_S:
            case Code.Endfinally:
            case Code.Endfilter:

                exceptions.Translate(cilInst);
                break;

            case Code.Newarr:

                arrays.New(cilInst.Operand);
                break;

            case Code.Ldlen:

                arrays.Length();
                break;

            case Code.Ldelema:

                arrays.Address(null, cilInst);
                break;

            case Code.Ldelem_I1:
            case Code.Ldelem_U1:
            case Code.Ldelem_I2:
            case Code.Ldelem_U2:
            case Code.Ldelem_I4:
            case Code.Ldelem_U4:
            case Code.Ldelem_I8:
            case Code.Ldelem_I:
            case Code.Ldelem_R4:
            case Code.Ldelem_R8:
            case Code.Ldelem_Ref:
            case Code.Ldelem_Any:

                arrays.Load(cilOp, cilInst.Operand, cilInst);
                break;

            case Code.Stelem_I1:
            case Code.Stelem_I2:
            case Code.Stelem_I4:
            case Code.Stelem_I8:
            case Code.Stelem_I:
            case Code.Stelem_R4:
            case Code.Stelem_R8:
            case Code.Stelem_Any:
            case Code.Stelem_Ref:

                arrays.Store(cilOp, cilInst);
                break;

            case Code.Ldftn:
            case Code.Ldvirtftn:

                Delegate.LoadFunction(code, cilInst);
                break;

            case Code.Sizeof:

                CodeSpan.Sizeof(cilInst.Operand, code);
                break;

            case Code.Localloc:

                CodeSpan.Localloc(code);
                break;

            /*  instructions not handled:
             *      Jmp, Calli, Cpobj, Refanyval, Ckfinite, Mkrefany, Arglist,
             *      Tail, Cpblk, Initblk, No, Refanytype, */

            default:
                throw new InvalidProgramException();
            }
        }
Пример #2
0
        public void New(CilType elemType, int numDims, bool arrayTypeOnStack = false)
        {
            var elemTypeForArray = elemType.IsGenericParameter
                                 ? CilType.From(JavaType.ObjectType) : elemType;
            var arrayType = elemTypeForArray.AdjustRank(numDims);

            if (elemType.IsGenericParameter)
            {
                /*if (numDims != 1)
                 *  throw new Exception("unsupported number of dimensions in generic array");*/

                if (!arrayTypeOnStack)
                {
                    GenericUtil.LoadMaybeGeneric(elemType, code);
                }

                var parameters = new List <JavaFieldRef>();
                for (int i = 0; i < numDims; i++)
                {
                    parameters.Add(new JavaFieldRef("", JavaType.IntegerType));
                }
                parameters.Add(new JavaFieldRef("", CilType.SystemTypeType));

                code.NewInstruction(0xB8 /* invokestatic */, SystemArrayType,
                                    new JavaMethodRef("New", JavaType.ObjectType, parameters));

                stackMap.PopStack(CilMain.Where);   // type

                while (numDims-- > 0)
                {
                    stackMap.PopStack(CilMain.Where);
                }

                arrayType = GenericArrayType;
            }

            else if (elemType.IsReference || numDims > 1)
            {
                if (numDims == 1)
                {
                    code.NewInstruction(0xBD /* anewarray */, elemType, null);
                }
                else
                {
                    code.NewInstruction(0xC5 /* multianewarray */, arrayType, numDims);
                }

                for (int i = 0; i < numDims; i++)
                {
                    stackMap.PopStack(CilMain.Where);
                }

                stackMap.PushStack(arrayType);  // arrayObj

                if (elemType.ArrayRank != 0)
                {
                    if (numDims == 1)
                    {
                        // notify the array support methods in baselib that this
                        // is a jagged array, i.e. a single dimension array with
                        // an element type that is also an array.  for arrays of
                        // generic type, see system.Array.New() in baselib.

                        stackMap.PushStack(JavaType.ObjectType);
                        code.NewInstruction(0x59 /* dup */, null, null);
                        code.NewInstruction(0xB8 /* invokestatic */, SystemArrayType,
                                            new JavaMethodRef("MarkJagged",
                                                              JavaType.VoidType, JavaType.ObjectType));
                        stackMap.PopStack(CilMain.Where);
                    }
                }

                else if (elemType.IsValueClass)
                {
                    code.NewInstruction(0x59 /* dup */, null, null);
                    stackMap.PushStack(arrayType);      // arrayCopy

                    if (elemType.HasGenericParameters)
                    {
                        // array of a value class ArrayElement<T>, pass this type
                        // as the second parameter to system.Array.Initialize

                        GenericUtil.LoadMaybeGeneric(elemType, code);

                        // third parameter is null
                        code.NewInstruction(0x01 /* aconst_null */, null, null);
                        stackMap.PushStack(JavaType.ObjectType);
                    }
                    else
                    {
                        // array of a plain value class, pass a constructed object
                        // as the third parameter to system.Array.Initialize

                        // second parameter is null
                        code.NewInstruction(0x01 /* aconst_null */, null, null);
                        stackMap.PushStack(CilType.SystemTypeType);

                        // model parameter is a new object
                        code.NewInstruction(0xBB /* new */, elemType.AsWritableClass, null);
                        stackMap.PushStack(elemType);
                        code.NewInstruction(0x59 /* dup */, null, null);
                        stackMap.PushStack(elemType);
                        code.NewInstruction(0xB7 /* invokespecial */, elemType.AsWritableClass,
                                            new CilMethod(elemType));
                        stackMap.PopStack(CilMain.Where);
                    }

                    code.NewInstruction(0x12 /* ldc */, null, numDims);
                    stackMap.PushStack(JavaType.IntegerType);

                    code.NewInstruction(0xB8 /* invokestatic */, SystemArrayType, InitArrayMethod);

                    stackMap.PopStack(CilMain.Where);   // numDims
                    stackMap.PopStack(CilMain.Where);   // elemType
                    stackMap.PopStack(CilMain.Where);   // arrayType
                    stackMap.PopStack(CilMain.Where);   // arrayCopy
                }

                stackMap.PopStack(CilMain.Where);   // arrayObj
            }
            else
            {
                if (numDims == 1)
                {
                    var length = stackMap.PopStack(CilMain.Where);
                    stackMap.PushStack(length);
                    if (length.Equals(JavaType.LongType))
                    {
                        CodeNumber.Conversion(code, Code.Conv_Ovf_I4, null);
                    }
                }

                code.NewInstruction(0xBC /* newarray */, null, elemType.NewArrayType);

                while (numDims-- > 0)
                {
                    stackMap.PopStack(CilMain.Where);
                }
            }

            stackMap.PushStack(arrayType);
        }