Beispiel #1
0
        public static void Instance(JavaCode code, CodeLocals locals, Mono.Cecil.Cil.Instruction cilInst)
        {
            if (cilInst.Operand is TypeReference cilType && cilInst.Next != null)
            {
                var stackTop = (CilType)code.StackMap.PopStack(CilMain.Where);
                if (!stackTop.IsReference)
                {
                    throw new InvalidProgramException(); // top of stack is a primitive type
                }
                var      castType  = (CilType)CilType.From(cilType);
                JavaType castClass = CilType.From(cilType).AsWritableClass;

                if (GenericUtil.ShouldCallGenericCast(stackTop, castType) ||
                    castType.IsGenericParameter)
                {
                    code.StackMap.PushStack(stackTop);
                    // casting to a generic type is done via GenericType.TestCast
                    GenericUtil.CastToGenericType(cilType, 0, code);
                    code.StackMap.PopStack(CilMain.Where);  // stackTop
                    if (!castType.IsGenericParameter)
                    {
                        code.NewInstruction(0xC0 /* checkcast */, castClass, null);
                    }
                    code.StackMap.PushStack(castClass);
                }

                else if (CodeArrays.CheckCast(castType, false, code))
                {
                    // if casting to Object[], ValueType[], to an array of
                    // interface type, or to an array of a generic parameter,
                    // then CodeArrays.CheckCast already generated a call to
                    // system.Array.CheckCast in baselib, and we are done here

                    if (!castType.IsGenericParameter)
                    {
                        // avoid cast since T[] might be a primitive array
                        code.NewInstruction(0xC0 /* checkcast */, castClass, null);
                    }
                    code.StackMap.PushStack(castClass);
                }

                //
                // the cil 'isinst' casts the operand to the requested class,
                // but the jvm 'instanceof' only returns zero or one.  so we
                // also use 'checkcast' to get the jvm to acknowledge the cast
                //
                // however, if the cil 'isinst' is immediately followed by
                // 'brtrue' or 'brfalse' then we don't have to actually cast
                //

                else if (!TestForBranch(code, castClass, cilInst.Next))
                {
                    ushort nextLabel  = (ushort)cilInst.Next.Offset;
                    int    localIndex = locals.GetTempIndex(stackTop);

                    TestAndCast(code, castClass, stackTop, nextLabel, localIndex);

                    locals.FreeTempIndex(localIndex);
                }
            }
Beispiel #2
0
        public static void Straight(JavaCode code, Code cilOp, CodeLocals locals,
                                    Mono.Cecil.Cil.Instruction cilInst)
        {
            //
            // a straight branch maps to the corresponding compare logic
            // (beq = ceq, bgt = cgt, blt = clt), plus logic for brtrue.
            //

            byte   op;
            ushort nextInstOffset = 0;

            if (cilOp == Code.Br || cilOp == Code.Br_S)
            {
                if (cilInst.Operand is Mono.Cecil.Cil.Instruction inst)
                {
                    if (inst == cilInst.Next)
                    {
                        op = 0x00; // nop
                    }
                    else
                    {
                        op = 0xA7; // goto
                        if (cilInst.Next != null)
                        {
                            nextInstOffset = (ushort)cilInst.Next.Offset;
                        }
                    }
                }
                else
                {
                    throw new InvalidProgramException();
                }
            }
            else
            {
                var stackTop = code.StackMap.PopStack(CilMain.Where);
                op = Common(code, cilOp, cilInst, stackTop);
            }

            Finish(code, locals, cilInst, op);

            if (nextInstOffset != 0)
            {
                if (!code.StackMap.LoadFrame(nextInstOffset, true, null))
                {
                    if (op == 0xA7 /* goto */)
                    {
                        locals.TrackUnconditionalBranch(cilInst);
                    }
                }
            }
        }
Beispiel #3
0
        public CodeExceptions(MethodBody body, JavaCode _code, CodeLocals locals)
        {
            tryClauses   = new List <TryClause>();
            catchClauses = new Dictionary <int, CatchClause>();
            code         = _code;
            stackMap     = code.StackMap;
            this.locals  = locals;

            if (body.HasExceptionHandlers)
            {
                if (!InitExceptionClauses(body))
                {
                    throw CilMain.Where.Exception("error in exception handlers data");
                }
            }
        }
Beispiel #4
0
        static void Finish(JavaCode code, CodeLocals locals,
                           Mono.Cecil.Cil.Instruction cilInst, byte op)
        {
            var inst = (Mono.Cecil.Cil.Instruction)cilInst.Operand;

            bool isNop;

            if (op == 0x00 || op == 0x57 || op == 0x58) // nop, pop, pop2
            {
                isNop = true;
            }
            else
            {
                isNop = false;
                int diff = cilInst.Offset - inst.Offset;
                if (diff < -0x2000 || diff > 0x2000)
                {
                    // branch instructions use 16-bits for the signed offset.
                    // for farther branches, we have to negate the condition,
                    // and insert a 32-bit 'goto_w' instruction.

                    if (cilInst.Next != null)
                    {
                        op = NegateCondition(op);
                        var nextOffset = (ushort)cilInst.Next.Offset;
                        code.NewInstruction(op, null, nextOffset);
                        code.StackMap.SaveFrame(nextOffset, true, CilMain.Where);
                    }

                    op = 0xC8;
                }
            }

            code.NewInstruction(op, null, (ushort)inst.Offset);

            if (!isNop)  // no stack frame for 'nop' or 'pop'
            {
                var resetLocals =
                    code.StackMap.SaveFrame((ushort)inst.Offset, true, CilMain.Where);

                if (resetLocals != null)
                {
                    ResetLocalsOutOfScope(code.StackMap, locals, resetLocals, cilInst, inst);
                }
            }
        }
Beispiel #5
0
        void Process(int numCastableInterfaces)
        {
            code = newMethod.Code = new JavaCode(newMethod);
            var oldLabel = code.SetLabel(0xFFFF);

            locals     = new CodeLocals(method, defMethod, code);
            arrays     = new CodeArrays(code, locals);
            exceptions = new CodeExceptions(defMethodBody, code, locals);

            InsertMethodInitCode(numCastableInterfaces);

            code.SetLabel(oldLabel);

            stackMap = code.StackMap;
            stackMap.SaveFrame(0, false, CilMain.Where);

            ProcessInstructions();

            (code.MaxLocals, code.MaxStack) = locals.GetMaxLocalsAndStack();
            locals.TrackUnconditionalBranch(null);
        }
Beispiel #6
0
 public CodeArrays(JavaCode _code, CodeLocals _locals)
 {
     locals   = _locals;
     code     = _code;
     stackMap = code.StackMap;
 }
Beispiel #7
0
        public static void Opposite(JavaCode code, Code cilOp, CodeLocals locals,
                                    Mono.Cecil.Cil.Instruction cilInst)
        {
            //
            // an opposite branch works by generating logic/opcode for
            // the opposite test (e.g. clt for bge), and an opposite
            // branch opcode (e.g. for bge, branch if clt returns zero)
            //

            var stackTop = code.StackMap.PopStack(CilMain.Where);

            bool isFloat = (stackTop.PrimitiveType == TypeCode.Single ||
                            stackTop.PrimitiveType == TypeCode.Double);

            if (cilOp == Code.Brfalse || cilOp == Code.Brfalse_S)
            {
                cilOp = Code.Brtrue;
            }
            else if (cilOp == Code.Bne_Un || cilOp == Code.Bne_Un_S)
            {
                cilOp = Code.Beq;
            }
            else if (cilOp == Code.Ble || cilOp == Code.Ble_S)
            {
                // for integer, this is the opposite of BGT
                // for float, this is the opposite of BGT.UN
                cilOp = isFloat ? Code.Bgt_Un : Code.Bgt;
            }
            else if (cilOp == Code.Ble_Un || cilOp == Code.Ble_Un_S)
            {
                // for integer, this is the opposite of BGT.UN
                // for float, this is the opposite of BGT
                cilOp = isFloat ? Code.Bgt : Code.Bgt_Un;
            }
            else if (cilOp == Code.Bge || cilOp == Code.Bge_S)
            {
                // for integer, this is the opposite of BLT
                // for float, this is the opposite of BLT.UN
                cilOp = isFloat ? Code.Blt_Un : Code.Blt;
            }
            else if (cilOp == Code.Bge_Un || cilOp == Code.Bge_Un_S)
            {
                // for integer, this is the opposite of BLT.UN
                // for float, this is the opposite of BLT
                cilOp = isFloat ? Code.Blt : Code.Blt_Un;
            }
            else
            {
                throw new InvalidProgramException();
            }

            //
            // change the branch test to the opposite result
            //

            byte op = Common(code, cilOp, cilInst, stackTop);

            op = NegateCondition(op);

            Finish(code, locals, cilInst, op);
        }