Beispiel #1
0
        internal JavaConstant.MethodHandle ToConstant(JavaWriter wtr)
        {
            int referenceIndex = -1;

            if (Kind <= HandleKind.PutStatic)
            {
                referenceIndex = wtr.ConstField(Class, Field);
            }
            else if (Kind <= HandleKind.NewInvokeSpecial)
            {
                if (IsInterfaceMethod)
                {
                    referenceIndex = wtr.ConstInterfaceMethod(Class, Method);
                }
                else
                {
                    referenceIndex = wtr.ConstMethod(Class, Method);
                }
            }
            else if (Kind == HandleKind.InvokeInterface && IsInterfaceMethod)
            {
                referenceIndex = wtr.ConstInterfaceMethod(Class, Method);
            }

            if (referenceIndex == -1)
            {
                throw wtr.Where.Exception("invalid method handle");
            }

            return(new JavaConstant.MethodHandle((byte)Kind, (ushort)referenceIndex));
        }
        void FillInstruction_ConstLoad(JavaWriter wtr, Instruction inst)
        {
            int  constantIndex = -1;
            byte op            = 0;

            if (inst.Data is long vLong)
            {
                if (FillInstruction_ConstLoad_Long(inst, vLong))
                {
                    return;
                }
                constantIndex = wtr.ConstLong(vLong);
                op            = 0x14;
            }

            else if (inst.Data is double vDouble)
            {
                if (FillInstruction_ConstLoad_Double(inst, vDouble))
                {
                    return;
                }
                constantIndex = wtr.ConstDouble(vDouble);
                op            = 0x14;
            }

            else
            {
                if (inst.Class != null)
                {
                    if (inst.Data is JavaFieldRef vField)
                    {
                        constantIndex = wtr.ConstField(inst.Class, vField);
                    }

                    else if (inst.Data is JavaMethodRef vMethod)
                    {
                        constantIndex = wtr.ConstMethod(inst.Class, vMethod);
                    }

                    else if (inst.Data == null)
                    {
                        constantIndex = wtr.ConstClass(inst.Class);
                    }
                }

                else if (inst.Data is int vInteger)
                {
                    if (FillInstruction_ConstLoad_Integer(inst, vInteger))
                    {
                        return;
                    }
                    constantIndex = wtr.ConstInteger(vInteger);
                }

                else if (inst.Data is float vFloat)
                {
                    if (FillInstruction_ConstLoad_Float(inst, vFloat))
                    {
                        return;
                    }
                    constantIndex = wtr.ConstFloat(vFloat);
                }

                else if (inst.Data is string vString)
                {
                    constantIndex = wtr.ConstString(vString);
                }

                op          = (byte)((constantIndex <= 255) ? 0x12 : 0x13);
                inst.Opcode = op;
            }

            if (constantIndex == -1)
            {
                throw wtr.Where.Exception("invalid constant in ldc/ldc_w/ldc2_w instruction");
            }

            if (op == 0x12)
            {
                inst.Bytes    = new byte[2];
                inst.Bytes[1] = (byte)constantIndex;
            }
            else
            {
                inst.Bytes    = new byte[3];
                inst.Bytes[1] = (byte)(constantIndex >> 8);
                inst.Bytes[2] = (byte)constantIndex;
            }
            inst.Bytes[0] = op;
        }
        bool FillInstruction_Const(JavaWriter wtr, Instruction inst, byte op)
        {
            int length = 3;
            int count  = 0;

            if (op >= 0x12 && op <= 0x14)
            {
                FillInstruction_ConstLoad(wtr, inst);
                return(true);
            }

            int constantIndex = -1;

            if (op >= 0xB2 && op <= 0xB5)
            {
                // getstatic/putstatic/getfield/putfield
                if (inst.Data is JavaFieldRef vField)
                {
                    constantIndex = wtr.ConstField(inst.Class, vField);
                }
            }

            else if (op >= 0xB6 && op <= 0xB8)
            {
                // invokevirtual/invokespecial/invokestatic
                if (inst.Data is JavaMethodRef vMethod)
                {
                    constantIndex = wtr.ConstMethod(inst.Class, vMethod);
                }
            }

            else if (op == 0xB9)
            {
                // invokeinterface
                if (inst.Data is JavaMethodRef vMethod)
                {
                    constantIndex = wtr.ConstInterfaceMethod(inst.Class, vMethod);
                    length        = 5;
                    count         = 1; // 'this' argument
                    int numArgs = vMethod.Parameters.Count;
                    for (int i = 0; i < numArgs; i++)
                    {
                        count += vMethod.Parameters[i].Type.Category;
                    }
                }
            }

            else if (op == 0xBA)
            {
                // invokedynamic
                if (inst.Data is JavaCallSite vCallSite)
                {
                    constantIndex = wtr.ConstInvokeDynamic(vCallSite);
                    length        = 5;
                }
            }

            else if (op >= 0xBB)
            {
                // new/anewarray/checkcast/instanceof/multianewarray
                constantIndex = wtr.ConstClass(inst.Class);

                if (op == 0xC5)
                {
                    length++;
                    count = (int)inst.Data;
                }
            }

            if (constantIndex == -1)
            {
                return(false);
            }

            inst.Bytes    = new byte[length];
            inst.Bytes[0] = op;
            inst.Bytes[1] = (byte)(constantIndex >> 8);
            inst.Bytes[2] = (byte)constantIndex;

            if (op == 0xB9 || op == 0xC5)
            {
                inst.Bytes[3] = (byte)count;
            }

            return(true);
        }