コード例 #1
0
        public ConstantPool Read(BinaryReader Reader)
        {
            ushort Count = Reader.ReadUInt16BE();

            ResultPool     = new ConstantPool();
            FiledConsts    = new bool[Count];
            FiledConsts[0] = true;
            RawData        = new byte[Count][];

            for (int i = 1; i < Count; i++)
            {
                Constant    Result = null;
                ConstantTag Tag    = (ConstantTag)Reader.ReadByte();

                switch (Tag)
                {
                case ConstantTag.Utf8:                  Result = new Constants.Utf8(); break;

                case ConstantTag.Integer:               Result = new Constants.Integer(); break;

                case ConstantTag.Float:                 Result = new Constants.Float(); break;

                case ConstantTag.Long:                  Result = new Constants.Long(); break;

                case ConstantTag.Double:                Result = new Constants.Double(); break;

                case ConstantTag.Class:                 Result = new Constants.Class(); break;

                case ConstantTag.String:                Result = new Constants.String(); break;

                case ConstantTag.FieldRef:              Result = new Constants.FieldRef(); break;

                case ConstantTag.MethodRef:             Result = new Constants.MethodRef(); break;

                case ConstantTag.InterfaceMethodRef:    Result = new Constants.InterfaceMethodRef(); break;

                case ConstantTag.NameAndType:           Result = new Constants.NameAndType(); break;

                case ConstantTag.MethodHandle:          Result = new Constants.MethodHandle(); break;

                case ConstantTag.MethodType:            Result = new Constants.MethodType(); break;

                case ConstantTag.InvokeDynamic:         Result = new Constants.InvokeDynamic(); break;
                }

                if (Result == null)
                {
                    ResultPool.ForceAddConstant(new Constants.Skip(), (ushort)i);
                    Messages.Message(MessageCode.JavaUnknownConstantTag, ((byte)Tag).ToString());
                    continue;
                }

                RawData[i] = Result.ReadData(Reader);
                ResultPool.ForceAddConstant(Result, (ushort)i);
                if (Result.Is8Byte())
                {
                    FiledConsts[++i] = true;
                }
            }

            for (int i = 1; i < Count; i++)
            {
                GetFilledConstant((ushort)i);
            }

            return(ResultPool);
        }
コード例 #2
0
        protected override bool CompareEqwals(Constant c)
        {
            InterfaceMethodRef Another = (InterfaceMethodRef)c;

            return((Class == Another.Class) && (Name == Another.Name) && (Descriptor == Another.Descriptor));
        }
コード例 #3
0
        private void CompileJmp(ILExpression e, ExpectType expect)
        {
            int argIndex = 0;

            if (thisMethod.HasThis)
            {
                codeGenerator.Add(Java.OpCodes.aload_0, null, e);
                argIndex++;
            }

            for (int i = 0; i < thisMethod.Parameters.Count; i++)
            {
                JavaPrimitiveType jp = JavaHelpers.InterTypeToJavaPrimitive(thisMethod.Parameters[i].Type);
                codeGenerator.AddLoad(jp, argIndex++);
                if (jp.IsDoubleSlot())
                {
                    argIndex++;
                }
            }

            InterMethod operand = resolver.Resolve((MethodReference)e.Operand, thisMethod.FullGenericArguments);

            CallType callType = CallType.Virtual;

            if (operand.IsStatic)
            {
                callType = CallType.Static;
            }
            else if (operand.DeclaringType.IsInterface)
            {
                callType = CallType.Interface;
            }
            else if ((operand.IsConstructor) || (operand.IsPrivate) ||
                     ((operand.IsSame(thisMethod)) && (thisMethod.DeclaringType.BaseType == operand.DeclaringType)))
            {
                callType = CallType.Special;
            }

            Java.Constant javaOperand = null;

            if (callType == CallType.Interface)
            {
                javaOperand = new Java.Constants.InterfaceMethodRef(
                    namesController.TypeNameToJava(operand.DeclaringType),
                    namesController.MethodNameToJava(operand.NewName),
                    namesController.GetMethodDescriptor(operand));
            }
            else
            {
                javaOperand = new Java.Constants.MethodRef(
                    namesController.TypeNameToJava(operand.DeclaringType),
                    namesController.MethodNameToJava(operand.NewName),
                    namesController.GetMethodDescriptor(operand));
            }

            switch (callType)
            {
            case CallType.Interface:
                codeGenerator.AddInstruction(new JavaInstruction(Java.OpCodes.invokeinterface, javaOperand, e));
                break;

            case CallType.Special:
                codeGenerator.AddInstruction(new JavaInstruction(Java.OpCodes.invokespecial, javaOperand, e));
                break;

            case CallType.Static:
                codeGenerator.AddInstruction(new JavaInstruction(Java.OpCodes.invokestatic, javaOperand, e));
                break;

            case CallType.Virtual:
                codeGenerator.AddInstruction(new JavaInstruction(Java.OpCodes.invokevirtual, javaOperand, e));
                break;
            }

            codeGenerator.AddReturn(JavaHelpers.InterTypeToJavaPrimitive(thisMethod.ReturnParameter.Type));
        }
コード例 #4
0
        private void CompileCall(ILExpression e, ExpectType expect)
        {
            InterMethod operand = resolver.Resolve((MethodReference)e.Operand, thisMethod.FullGenericArguments);

            if (operand.DeclaringType.Fullname == ClassNames.SystemThreadingMonitor.ClassName)
            {
                if (operand.Name == ClassNames.SystemThreadingMonitor.Enter)
                {
                    CompileMonitorEnter(e);
                    return;
                }

                if (operand.Name == ClassNames.SystemThreadingMonitor.Exit)
                {
                    CompileMonitorExit(e);
                    return;
                }
            }

            // Intrinsics that not poping real arguments
            if (operand.DeclaringType.Fullname == ClassNames.Intrinsics.ClassName)
            {
                if (operand.Name.Contains(ClassNames.Intrinsics.CreatePointerToArray))
                {
                    CompileIntrinsicCreatePointerToArray(e); return;
                }
                if (operand.Name == ClassNames.Intrinsics.GetBoxedDataFromPointer)
                {
                    CompileIntrinsicGetBoxedDataFromPointer(e); return;
                }
                if (operand.Name == ClassNames.Intrinsics.GetClass)
                {
                    CompileIntrinsicGetClass(e); return;
                }
            }

            if ((Program.BoxType == BoxingType.Java) && (operand.DeclaringType.Fullname == ClassNames.CorlibUtils) &&
                (operand.Name == ClassNames.ReboxMethod))
            {
                //Skip CIL2Java.Utils::Rebox in java boxing mode due optimizations
                CompileExpression(e.Arguments[0], expect);
                return;
            }

            if ((operand.IsConstructor) && (operand.DeclaringType.IsValueType) && (operand.Parameters.Count < e.Arguments.Count) &&
                (!thisMethod.IsConstructor))
            {
                // rebuild nodes from `call ctor(getVar(), [params])` to
                // setVar(newObj([params])

                ILExpression getVar = e.Arguments[0];
                e.Arguments.RemoveAt(0);
                e.Code      = ILCode.Newobj;
                getVar.Code = LoadVarInvert[getVar.Code];
                getVar.Arguments.Add(e);
                CompileExpression(getVar, expect);

                return;
            }

            if (operand.DeclaringType.IsArray)
            {
                CompileArrayCall(e, expect);
                return;
            }

            int argIndex = 0;

            if ((operand.HasThis) && (operand.Parameters.Count < e.Arguments.Count))
            {
                if (e.Prefixes != null)
                {
                    ILExpressionPrefix constrained = e.Prefixes.Where(P => P.Code == ILCode.Constrained).FirstOrDefault();
                    if (constrained != null)
                    {
                        InterType thisType = resolver.Resolve((TypeReference)constrained.Operand, thisMethod.FullGenericArguments);

                        if (thisType.IsPrimitive)
                        {
                            e.Arguments[argIndex].Code = GetAddrInvert[e.Arguments[argIndex].Code];
                            e.Arguments[argIndex]      = new ILExpression(ILCode.Box, null, e.Arguments[argIndex]);
                        }
                    }
                }

                CompileExpression(e.Arguments[argIndex++], ExpectType.Reference);
            }

            foreach (InterParameter param in operand.Parameters)
            {
                CompileExpression(e.Arguments[argIndex++], GetExpectType(param));
            }

            if (operand.IsVarArg)
            {
                codeGenerator
                .AddIntConst(e.Arguments.Count - argIndex)
                .Add(OpCodes.anewarray, new Java.Constants.Class(namesController.TypeNameToJava(ClassNames.JavaObject)), e);

                int i = 0;
                while (argIndex < e.Arguments.Count)
                {
                    codeGenerator
                    .Add(OpCodes.dup, null, e)
                    .AddIntConst(i++, e);

                    CompileExpression(e.Arguments[argIndex++], ExpectType.Boxed);
                    codeGenerator.Add(OpCodes.aastore, null, e);
                }
            }

            // Intrinsics that poping real arguments
            if (operand.DeclaringType.Fullname == ClassNames.Intrinsics.ClassName)
            {
                if (operand.Name == ClassNames.Intrinsics.monitorenter)
                {
                    codeGenerator.Add(Java.OpCodes.monitorenter, null, e);
                }
                if (operand.Name == ClassNames.Intrinsics.monitorexit)
                {
                    codeGenerator.Add(Java.OpCodes.monitorexit, null, e);
                }
                if (operand.Name == ClassNames.Intrinsics.lshr)
                {
                    codeGenerator.Add(Java.OpCodes.lshr, null, e);
                }
                if (operand.Name == ClassNames.Intrinsics.lushr)
                {
                    codeGenerator.Add(Java.OpCodes.lushr, null, e);
                }

                // UnsafeTypeConvert skip because:
                // Not any compiling. Just push argument, and it will auto became object type
                return;
            }

            CallType callType = CallType.Virtual;

            if (operand.IsStatic)
            {
                callType = CallType.Static;
            }
            else if (operand.DeclaringType.IsInterface)
            {
                callType = CallType.Interface;
            }
            else if ((operand.IsConstructor) || (operand.IsPrivate) ||
                     ((operand.IsSame(thisMethod)) && (thisMethod.DeclaringType.BaseType == operand.DeclaringType)))
            {
                callType = CallType.Special;
            }

            Java.Constant javaOperand = null;

            if (callType == CallType.Interface)
            {
                javaOperand = new Java.Constants.InterfaceMethodRef(
                    namesController.TypeNameToJava(operand.DeclaringType),
                    namesController.MethodNameToJava(operand.NewName),
                    namesController.GetMethodDescriptor(operand));
            }
            else
            {
                javaOperand = new Java.Constants.MethodRef(
                    namesController.TypeNameToJava(operand.DeclaringType),
                    namesController.MethodNameToJava(operand.NewName),
                    namesController.GetMethodDescriptor(operand));
            }

            switch (callType)
            {
            case CallType.Interface:
                codeGenerator.AddInstruction(new JavaInstruction(Java.OpCodes.invokeinterface, javaOperand, e));
                break;

            case CallType.Special:
                codeGenerator.AddInstruction(new JavaInstruction(Java.OpCodes.invokespecial, javaOperand, e));
                break;

            case CallType.Static:
                codeGenerator.AddInstruction(new JavaInstruction(Java.OpCodes.invokestatic, javaOperand, e));
                break;

            case CallType.Virtual:
                codeGenerator.AddInstruction(new JavaInstruction(Java.OpCodes.invokevirtual, javaOperand, e));
                break;
            }

            OnRestoreLocalByRefs();

            if ((!operand.ReturnParameter.Type.IsPrimitive) || (operand.ReturnParameter.Type.PrimitiveType != PrimitiveType.Void) ||
                (operand.ReturnParameter.IsBoxed) || (operand.ReturnParameter.IsJavaBoxed))
            {
                TranslateType(operand.ReturnParameter.Type, expect, e);
            }
        }
コード例 #5
0
        private void LinkPass1(Java.ConstantPool pool)
        {
            int offset = StartOffset;

            bool lastWide = false;

            for (int i = 0; i < outputCode.Count; i++)
            {
                JavaInstruction instr = outputCode[i];
                outputCodeOffsets.Add(instr, offset);

                object lastOperand = instr.Operand;
                if (instr.Operand is Java.Constant)
                {
                    instr.Operand = pool.AddConstant((Java.Constant)instr.Operand);
                }
                else if (instr.Operand is MultianewarrayOperand)
                {
                    MultianewarrayOperand operand = (MultianewarrayOperand)instr.Operand;
                    instr.Operand = pool.AddConstant(operand.ClassOperand) | (operand.DimensionsOperand << 16);
                }

                if (instr.Opcode == Java.OpCodes.ldc)
                {
                    if (((ushort)instr.Operand) > byte.MaxValue)
                    {
                        instr.Opcode = Java.OpCodes.ldc_w;
                    }
                }

                if (instr.Opcode == Java.OpCodes.invokeinterface)
                {
                    if (lastOperand is Java.Constants.MethodRef)
                    {
                        Java.Constants.MethodRef m = (Java.Constants.MethodRef)lastOperand;

                        lastOperand = new Java.Constants.InterfaceMethodRef(m.Class, m.Name, m.Descriptor);
                    }

                    byte   argsCount  = CalculateInterfaceCallArgsCount(((Java.Constants.InterfaceMethodRef)lastOperand).Descriptor);
                    ushort constIndex = (ushort)instr.Operand;
                    instr.Operand = (uint)(constIndex | ((argsCount + 1) << 24));
                }

                int size = Java.ByteCode.JavaInstructions[instr.Opcode].Size;
                if ((size == -1) && (instr.Opcode == Java.OpCodes.lookupswitch))
                {
                    LookupswitchOperand op = (LookupswitchOperand)lastOperand;
                    instr.Operand = op;

                    int paddingLendth = (4 - ((offset + 1) % 4)) % 4;

                    size = 1                      //opcode
                           + paddingLendth        //padding
                           + 4                    //default
                           + 4                    //npairs
                           + op.Pairs.Length * 8; //pairs count * pairs size (8 = 4 + 4)
                }

                if (lastWide)
                {
                    size     = (size - 1) * 2 + 1;
                    lastWide = false;
                }

                offset += size;

                if (instr.Opcode == Java.OpCodes.wide)
                {
                    lastWide = true;
                }
            }
        }