예제 #1
0
            internal override (JavaState newState, IEnumerable <MethodAction> actions) ActUpon(JavaState curState,
                                                                                               Dictionary <int, ActionBlock> blocks)
            {
                var noActions  = new MethodAction[0];
                var typeSystem = JavaAssemblyBuilder.Instance.TypeSystem;

                switch (Instr)
                {
                case JavaInstruction.nop:
                    return(curState, noActions);

                case JavaInstruction.aconst_null:
                    return(curState.Push(new ConstantValue(typeSystem.Object, null)), noActions);

                case JavaInstruction.iconst_m1:
                case JavaInstruction.iconst_0:
                case JavaInstruction.iconst_1:
                case JavaInstruction.iconst_2:
                case JavaInstruction.iconst_3:
                case JavaInstruction.iconst_4:
                case JavaInstruction.iconst_5:
                    return(curState
                           .Push(new ConstantValue(typeSystem.Int32, Instr - JavaInstruction.iconst_0)),
                           noActions);

                case JavaInstruction.lconst_0:
                case JavaInstruction.lconst_1:
                    return(curState
                           .Push(new ConstantValue(typeSystem.Int64, (long)(Instr - JavaInstruction.lconst_0)))
                           .Push(null),
                           noActions);

                case JavaInstruction.fconst_0:
                case JavaInstruction.fconst_1:
                case JavaInstruction.fconst_2:
                    return(curState
                           .Push(new ConstantValue(typeSystem.Single, (float)(Instr - JavaInstruction.fconst_0))),
                           noActions);

                case JavaInstruction.dconst_0:
                case JavaInstruction.dconst_1:
                    return(curState
                           .Push(new ConstantValue(typeSystem.Double, (double)(Instr - JavaInstruction.dconst_0)))
                           .Push(null),
                           noActions);

                case JavaInstruction.iload_0:
                case JavaInstruction.iload_1:
                case JavaInstruction.iload_2:
                case JavaInstruction.iload_3:
                {
                    var toLoad = curState.Load(Instr - JavaInstruction.iload_0);
                    return(curState.Push(toLoad), noActions);
                }

                case JavaInstruction.lload_0:
                case JavaInstruction.lload_1:
                case JavaInstruction.lload_2:
                case JavaInstruction.lload_3:
                {
                    var toLoad = curState.Load(Instr - JavaInstruction.lload_0);
                    return(curState.Push(toLoad).Push(null), noActions);
                }

                case JavaInstruction.fload_0:
                case JavaInstruction.fload_1:
                case JavaInstruction.fload_2:
                case JavaInstruction.fload_3:
                {
                    var toLoad = curState.Load(Instr - JavaInstruction.fload_0);
                    return(curState.Push(toLoad), noActions);
                }

                case JavaInstruction.dload_0:
                case JavaInstruction.dload_1:
                case JavaInstruction.dload_2:
                case JavaInstruction.dload_3:
                {
                    var toLoad = curState.Load(Instr - JavaInstruction.dload_0);
                    return(curState.Push(toLoad).Push(null), noActions);
                }

                case JavaInstruction.aload_0:
                case JavaInstruction.aload_1:
                case JavaInstruction.aload_2:
                case JavaInstruction.aload_3:
                {
                    var toLoad = curState.Load(Instr - JavaInstruction.aload_0);
                    return(curState.Push(toLoad), noActions);
                }

                case JavaInstruction.iaload:
                case JavaInstruction.faload:
                case JavaInstruction.baload:
                case JavaInstruction.caload:
                case JavaInstruction.saload:
                case JavaInstruction.aaload:
                case JavaInstruction.laload:
                case JavaInstruction.daload:
                {
                    var newState = curState.Pop(out var index).Pop(out var array);
                    var value    = new CalculatedValue(array.ActualType.GetElementType());
                    newState = newState.Push(value);
                    if (Instr == JavaInstruction.laload || Instr == JavaInstruction.daload)
                    {
                        newState = newState.Push(null);
                    }
                    return(newState, new[] { new ArrayIndexAction(value, array, index) });
                }

                case JavaInstruction.istore_0:
                case JavaInstruction.istore_1:
                case JavaInstruction.istore_2:
                case JavaInstruction.istore_3:
                {
                    return(curState.Pop(out var v).Store(Instr - JavaInstruction.istore_0, v), noActions);
                }

                case JavaInstruction.lstore_0:
                case JavaInstruction.lstore_1:
                case JavaInstruction.lstore_2:
                case JavaInstruction.lstore_3:
                {
                    return(curState.Pop().Pop(out var v).Store(Instr - JavaInstruction.lstore_0, v), noActions);
                }

                case JavaInstruction.fstore_0:
                case JavaInstruction.fstore_1:
                case JavaInstruction.fstore_2:
                case JavaInstruction.fstore_3:
                {
                    return(curState.Pop(out var v).Store(Instr - JavaInstruction.fstore_0, v), noActions);
                }

                case JavaInstruction.dstore_0:
                case JavaInstruction.dstore_1:
                case JavaInstruction.dstore_2:
                case JavaInstruction.dstore_3:
                {
                    return(curState.Pop().Pop(out var v).Store(Instr - JavaInstruction.dstore_0, v), noActions);
                }

                case JavaInstruction.astore_0:
                case JavaInstruction.astore_1:
                case JavaInstruction.astore_2:
                case JavaInstruction.astore_3:
                {
                    return(curState.Pop(out var v).Store(Instr - JavaInstruction.astore_0, v), noActions);
                }

                case JavaInstruction.iastore:
                case JavaInstruction.fastore:
                case JavaInstruction.bastore:
                case JavaInstruction.castore:
                case JavaInstruction.sastore:
                case JavaInstruction.aastore:
                case JavaInstruction.lastore:
                case JavaInstruction.dastore:
                {
                    var newState = curState;
                    if (Instr == JavaInstruction.lastore || Instr == JavaInstruction.dastore)
                    {
                        newState = newState.Pop();
                    }
                    newState = newState.Pop(out var value).Pop(out var index).Pop(out var array);
                    return(newState, new[] { new ArraySetAction(array, index, value) });
                }

                case JavaInstruction.pop:
                    return(curState.Pop(out _), noActions);

                case JavaInstruction.pop2:
                    return(curState.Pop().Pop(out _), noActions);

                case JavaInstruction.dup:
                {
                    return(
                        curState
                        .Pop(out var value)
                        .Push(value).Push(value),
                        noActions);
                }

                case JavaInstruction.dup_x1:
                {
                    return(
                        curState
                        .Pop(out var value1).Pop(out var value2)
                        .Push(value1).Push(value2).Push(value1),
                        noActions);
                }

                case JavaInstruction.dup_x2:
                {
                    return(
                        curState
                        .Pop(out var value1).Pop(out var value2).Pop(out var value3)
                        .Push(value1).Push(value3).Push(value2).Push(value1),
                        noActions);
                }

                case JavaInstruction.dup2:
                {
                    return(
                        curState
                        .Pop(out var value1).Pop(out var value2)
                        .Push(value2).Push(value1).Push(value2).Push(value1),
                        noActions);
                }

                case JavaInstruction.dup2_x1:
                {
                    return(
                        curState
                        .Pop(out var value1).Pop(out var value2).Pop(out var value3)
                        .Push(value2).Push(value1).Push(value3).Push(value2).Push(value1),
                        noActions);
                }

                case JavaInstruction.dup2_x2:
                {
                    return(
                        curState
                        .Pop(out var value1).Pop(out var value2).Pop(out var value3).Pop(out var value4)
                        .Push(value2).Push(value1).Push(value4).Push(value3).Push(value2).Push(value1),
                        noActions);
                }

                case JavaInstruction.swap:
                {
                    return(
                        curState
                        .Pop(out var value1).Pop(out var value2)
                        .Push(value1).Push(value2),
                        noActions);
                }

                case JavaInstruction.iadd:  return(BinaryOp <int, int>(curState, false, (x, y) => x + y, typeSystem.Int32, BinaryOperationAction.Creator(BinaryOperationAction.Op.Add)));

                case JavaInstruction.ladd:  return(BinaryOp <long, long>(curState, true, (x, y) => x + y, typeSystem.Int64, BinaryOperationAction.Creator(BinaryOperationAction.Op.Add)));

                case JavaInstruction.fadd:  return(BinaryOp <float, float>(curState, false, (x, y) => x + y, typeSystem.Single, BinaryOperationAction.Creator(BinaryOperationAction.Op.Add)));

                case JavaInstruction.dadd:  return(BinaryOp <double, double>(curState, true, (x, y) => x + y, typeSystem.Double, BinaryOperationAction.Creator(BinaryOperationAction.Op.Add)));

                case JavaInstruction.isub:  return(BinaryOp <int, int>(curState, false, (x, y) => x - y, typeSystem.Int32, BinaryOperationAction.Creator(BinaryOperationAction.Op.Sub)));

                case JavaInstruction.lsub:  return(BinaryOp <long, long>(curState, true, (x, y) => x - y, typeSystem.Int64, BinaryOperationAction.Creator(BinaryOperationAction.Op.Sub)));

                case JavaInstruction.fsub:  return(BinaryOp <float, float>(curState, false, (x, y) => x - y, typeSystem.Single, BinaryOperationAction.Creator(BinaryOperationAction.Op.Sub)));

                case JavaInstruction.dsub:  return(BinaryOp <double, double>(curState, true, (x, y) => x - y, typeSystem.Double, BinaryOperationAction.Creator(BinaryOperationAction.Op.Sub)));

                case JavaInstruction.imul:  return(BinaryOp <int, int>(curState, false, (x, y) => x * y, typeSystem.Int32, BinaryOperationAction.Creator(BinaryOperationAction.Op.Mul)));

                case JavaInstruction.lmul:  return(BinaryOp <long, long>(curState, true, (x, y) => x * y, typeSystem.Int64, BinaryOperationAction.Creator(BinaryOperationAction.Op.Mul)));

                case JavaInstruction.fmul:  return(BinaryOp <float, float>(curState, false, (x, y) => x * y, typeSystem.Single, BinaryOperationAction.Creator(BinaryOperationAction.Op.Mul)));

                case JavaInstruction.dmul:  return(BinaryOp <double, double>(curState, true, (x, y) => x * y, typeSystem.Double, BinaryOperationAction.Creator(BinaryOperationAction.Op.Mul)));

                case JavaInstruction.idiv:  return(BinaryOp <int, int>(curState, false, (x, y) => x / y, typeSystem.Int32, BinaryOperationAction.Creator(BinaryOperationAction.Op.Div)));

                case JavaInstruction.ldiv:  return(BinaryOp <long, long>(curState, true, (x, y) => x / y, typeSystem.Int64, BinaryOperationAction.Creator(BinaryOperationAction.Op.Div)));

                case JavaInstruction.fdiv:  return(BinaryOp <float, float>(curState, false, (x, y) => x / y, typeSystem.Single, BinaryOperationAction.Creator(BinaryOperationAction.Op.Div)));

                case JavaInstruction.ddiv:  return(BinaryOp <double, double>(curState, true, (x, y) => x / y, typeSystem.Double, BinaryOperationAction.Creator(BinaryOperationAction.Op.Div)));

                case JavaInstruction.irem:  return(BinaryOp <int, int>(curState, false, (x, y) => x % y, typeSystem.Int32, BinaryOperationAction.Creator(BinaryOperationAction.Op.Rem)));

                case JavaInstruction.lrem:  return(BinaryOp <long, long>(curState, true, (x, y) => x % y, typeSystem.Int64, BinaryOperationAction.Creator(BinaryOperationAction.Op.Rem)));

                case JavaInstruction.frem:  return(BinaryOp <float, float>(curState, false, (x, y) => x % y, typeSystem.Single, BinaryOperationAction.Creator(BinaryOperationAction.Op.Rem)));

                case JavaInstruction.drem:  return(BinaryOp <double, double>(curState, true, (x, y) => x % y, typeSystem.Double, BinaryOperationAction.Creator(BinaryOperationAction.Op.Rem)));

                case JavaInstruction.ishl:  return(BinaryOp <int, int>(curState, false, (x, y) => x << y, typeSystem.Int32, BinaryOperationAction.Creator(BinaryOperationAction.Op.Shl)));

                case JavaInstruction.lshl:  return(BinaryOp <long, int>(curState, true, (x, y) => x << y, typeSystem.Int64, BinaryOperationAction.Creator(BinaryOperationAction.Op.Shl), true));

                case JavaInstruction.ishr:  return(BinaryOp <int, int>(curState, false, (x, y) => x >> y, typeSystem.Int32, BinaryOperationAction.Creator(BinaryOperationAction.Op.Shr)));

                case JavaInstruction.lshr:  return(BinaryOp <long, int>(curState, true, (x, y) => x >> y, typeSystem.Int64, BinaryOperationAction.Creator(BinaryOperationAction.Op.Shr), true));

                case JavaInstruction.iushr: return(BinaryOp <int, int>(curState, false, (x, y) => (int)((uint)x >> y), typeSystem.Int32, BinaryOperationAction.Creator(BinaryOperationAction.Op.Ushr)));

                case JavaInstruction.lushr: return(BinaryOp <long, int>(curState, true, (x, y) => (long)((ulong)x >> y), typeSystem.Int64, BinaryOperationAction.Creator(BinaryOperationAction.Op.Ushr), true));

                case JavaInstruction.iand:  return(BinaryOp <int, int>(curState, false, (x, y) => x & y, typeSystem.Int32, BinaryOperationAction.Creator(BinaryOperationAction.Op.And)));

                case JavaInstruction.land:  return(BinaryOp <long, long>(curState, true, (x, y) => x & y, typeSystem.Int64, BinaryOperationAction.Creator(BinaryOperationAction.Op.And)));

                case JavaInstruction.ior:   return(BinaryOp <int, int>(curState, false, (x, y) => x | y, typeSystem.Int32, BinaryOperationAction.Creator(BinaryOperationAction.Op.Or)));

                case JavaInstruction.lor:   return(BinaryOp <long, long>(curState, true, (x, y) => x | y, typeSystem.Int64, BinaryOperationAction.Creator(BinaryOperationAction.Op.Or)));

                case JavaInstruction.ixor:  return(BinaryOp <int, int>(curState, false, (x, y) => x ^ y, typeSystem.Int32, BinaryOperationAction.Creator(BinaryOperationAction.Op.Xor)));

                case JavaInstruction.lxor:  return(BinaryOp <long, long>(curState, true, (x, y) => x ^ y, typeSystem.Int64, BinaryOperationAction.Creator(BinaryOperationAction.Op.Xor)));

                case JavaInstruction.ineg: return(UnaryOp <int, int>(curState, false, false, x => - x, typeSystem.Int32, UnaryOperationAction.Creator(UnaryOperationAction.Op.Neg)));

                case JavaInstruction.lneg: return(UnaryOp <long, long>(curState, true, true, x => - x, typeSystem.Int64, UnaryOperationAction.Creator(UnaryOperationAction.Op.Neg)));

                case JavaInstruction.fneg: return(UnaryOp <float, float>(curState, false, false, x => - x, typeSystem.Single, UnaryOperationAction.Creator(UnaryOperationAction.Op.Neg)));

                case JavaInstruction.dneg: return(UnaryOp <double, double>(curState, true, true, x => - x, typeSystem.Double, UnaryOperationAction.Creator(UnaryOperationAction.Op.Neg)));

                case JavaInstruction.l2i: return(UnaryOp <long, int>(curState, true, false, x => (int)x, typeSystem.Int32, UnaryOperationAction.Creator(UnaryOperationAction.Op.ToI)));

                case JavaInstruction.f2i: return(UnaryOp <float, int>(curState, false, false, x => (int)x, typeSystem.Int32, UnaryOperationAction.Creator(UnaryOperationAction.Op.ToI)));

                case JavaInstruction.d2i: return(UnaryOp <double, int>(curState, true, false, x => (int)x, typeSystem.Int32, UnaryOperationAction.Creator(UnaryOperationAction.Op.ToI)));

                case JavaInstruction.i2l: return(UnaryOp <int, long>(curState, false, true, x => (long)x, typeSystem.Int64, UnaryOperationAction.Creator(UnaryOperationAction.Op.ToL)));

                case JavaInstruction.f2l: return(UnaryOp <float, long>(curState, false, true, x => (long)x, typeSystem.Int64, UnaryOperationAction.Creator(UnaryOperationAction.Op.ToL)));

                case JavaInstruction.d2l: return(UnaryOp <double, long>(curState, true, true, x => (long)x, typeSystem.Int64, UnaryOperationAction.Creator(UnaryOperationAction.Op.ToL)));

                case JavaInstruction.i2f: return(UnaryOp <int, float>(curState, false, false, x => (float)x, typeSystem.Single, UnaryOperationAction.Creator(UnaryOperationAction.Op.ToF)));

                case JavaInstruction.l2f: return(UnaryOp <long, float>(curState, true, false, x => (float)x, typeSystem.Single, UnaryOperationAction.Creator(UnaryOperationAction.Op.ToF)));

                case JavaInstruction.d2f: return(UnaryOp <double, float>(curState, true, false, x => (float)x, typeSystem.Single, UnaryOperationAction.Creator(UnaryOperationAction.Op.ToF)));

                case JavaInstruction.i2d: return(UnaryOp <int, double>(curState, false, true, x => (double)x, typeSystem.Double, UnaryOperationAction.Creator(UnaryOperationAction.Op.ToD)));

                case JavaInstruction.l2d: return(UnaryOp <long, double>(curState, true, true, x => (double)x, typeSystem.Double, UnaryOperationAction.Creator(UnaryOperationAction.Op.ToD)));

                case JavaInstruction.f2d: return(UnaryOp <float, double>(curState, false, true, x => (double)x, typeSystem.Double, UnaryOperationAction.Creator(UnaryOperationAction.Op.ToD)));

                case JavaInstruction.i2b: return(UnaryOp <int, int>(curState, false, false, x => (sbyte)x, typeSystem.Byte, UnaryOperationAction.Creator(UnaryOperationAction.Op.ToB)));

                case JavaInstruction.i2c: return(UnaryOp <int, int>(curState, false, false, x => (char)x, typeSystem.Char, UnaryOperationAction.Creator(UnaryOperationAction.Op.ToC)));

                case JavaInstruction.i2s: return(UnaryOp <int, int>(curState, false, false, x => (short)x, typeSystem.Int16, UnaryOperationAction.Creator(UnaryOperationAction.Op.ToS)));

                case JavaInstruction.lcmp:
                    return(BinaryOp <long, long>(curState, true, null, typeSystem.Int32, BinaryOperationAction.Creator(BinaryOperationAction.Op.Lcmp), false, true));

                case JavaInstruction.fcmpg:
                    return(BinaryOp <float, float>(curState, false, null, typeSystem.Int32, BinaryOperationAction.Creator(BinaryOperationAction.Op.Fcmpg), false, true));

                case JavaInstruction.fcmpl:
                    return(BinaryOp <float, float>(curState, false, null, typeSystem.Int32, BinaryOperationAction.Creator(BinaryOperationAction.Op.Fcmpl), false, true));

                case JavaInstruction.dcmpg:
                    return(BinaryOp <double, double>(curState, true, null, typeSystem.Int32, BinaryOperationAction.Creator(BinaryOperationAction.Op.Fcmpg), false, true));

                case JavaInstruction.dcmpl:
                    return(BinaryOp <double, double>(curState, true, null, typeSystem.Int32, BinaryOperationAction.Creator(BinaryOperationAction.Op.Fcmpl), false, true));

                case JavaInstruction.ireturn:
                case JavaInstruction.freturn:
                case JavaInstruction.areturn:
                    return(Return(curState, false));

                case JavaInstruction.lreturn:
                case JavaInstruction.dreturn:
                    return(Return(curState, true));

                case JavaInstruction.@return:
                    return(Return(curState, false, true));

                case JavaInstruction.arraylength:
                {
                    var newState = curState.Pop(out var array);
                    var length   = new CalculatedValue(typeSystem.Int32);
                    return(newState.Push(length), new[] { new ArrayLengthAction(length, array) });
                }

                case JavaInstruction.athrow:
                {
                    curState.Pop(out var exc);
                    return(null, new[] { new ThrowAction(exc) });
                }

                case JavaInstruction.monitorenter:
                case JavaInstruction.monitorexit:
                {
                    return(curState.Pop(out var exc), new[] { new MonitorAction(exc, Instr == JavaInstruction.monitorenter) });
                }

                default:
                    throw new NotImplementedException($"{Instr} as Niladic");
                }
            }
예제 #2
0
        public (IEnumerable <MethodAction> acts, JavaState curState, JavaState newTarget) MapTo(JavaState targetState)
        {
            // next we map target into the current stack
            var target = targetState._stack.ToArray();
            var cur    = _stack.ToArray();

            var mappings = new List <(JavaValue, JavaValue)>();

            for (int i = 0; i < Math.Min(target.Length, cur.Length); i++)
            {
                if (target[i] == cur[i])
                {
                    continue;
                }
                mappings.Add((target[i], cur[i]));
                cur[i] = target[i];
            }

            // now we do the locals
            var resDict   = _locals;
            var newTarget = targetState;

            foreach (var(index, value) in _locals)
            {
                if (!targetState._locals.TryGetValue(index, out var targetValue))
                {
                    newTarget = newTarget.Store(index, value);
                    continue;
                }
                if (targetValue == value)
                {
                    continue;
                }

                mappings.Add((targetValue, value));
                resDict = resDict.SetItem(index, targetValue);
            }

            //foreach (var (index, _) in targetState._locals)
            //{
            //    Debug.Assert(_locals.ContainsKey(index)); // just to be sure
            //}

            return(mappings.Any() ? new[] { new MappingAction(mappings) } : new MethodAction[0], new JavaState(ImmutableStack.Create(cur.Reverse().ToArray()), resDict), newTarget);
        }