Beispiel #1
0
 public BinaryOperationAction(CalculatedValue target, Op operation, JavaValue value1, JavaValue value2)
 {
     Target    = target ?? throw new ArgumentNullException(nameof(target));
     Operation = operation;
     Value1    = value1 ?? throw new ArgumentNullException(nameof(value1));
     Value2    = value2 ?? throw new ArgumentNullException(nameof(value2));
 }
Beispiel #2
0
        public InvokeAction(CalculatedValue target, JavaValue instance, MethodReference method, JavaValue[] args, bool virt = false)
        {
            Target   = target;
            Instance = instance;
            Method   = method;
            Args     = args;
            Virtual  = virt;

            if (Instance == null)
            {
                Debug.Assert(!Virtual || !Method.HasThis);
            }
        }
Beispiel #3
0
        public (List <MethodAction>, JavaState) Unconst()
        {
            var actions   = new List <MethodAction>();
            var newStack  = new List <JavaValue>();
            var newLocals = new Dictionary <int, JavaValue>();

            foreach (var st in _stack.Reverse())
            {
                if (st?.IsConst == true)
                {
                    var v = new CalculatedValue(st.ActualType);
                    actions.Add(new ConstantSetAction(v, st));
                    newStack.Add(v);
                }
                else
                {
                    newStack.Add(st);
                }
            }

            foreach (var(key, value) in _locals)
            {
                if (value?.IsConst == true)
                {
                    var v = new CalculatedValue(value.ActualType);
                    actions.Add(new ConstantSetAction(v, value));
                    newLocals.Add(key, v);
                }
                else
                {
                    newLocals.Add(key, value);
                }
            }

            return(actions,
                   new JavaState(ImmutableStack.Create(newStack.ToArray()), newLocals.ToImmutableDictionary()));
        }
Beispiel #4
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");
                }
            }
Beispiel #5
0
 public ConstructorAction(CalculatedValue target, MethodReference method, JavaValue[] args)
 {
     Target = target;
     Method = method;
     Args   = args;
 }
Beispiel #6
0
 public GetFieldAction(CalculatedValue target, JavaValue from, FieldReference field)
 {
     Target = target;
     From   = @from;
     Field  = field;
 }
Beispiel #7
0
 public GetStaticAction(CalculatedValue target, FieldReference field)
 {
     Target = target;
     Field  = field;
 }
Beispiel #8
0
 public ArrayIndexAction(CalculatedValue target, JavaValue array, JavaValue index)
 {
     Target = target;
     Array  = array;
     Index  = index;
 }
Beispiel #9
0
 public MultiNewArrayAction(CalculatedValue target, TypeReference targetType, JavaValue[] dimensions)
 {
     TargetType = targetType;
     Dimensions = dimensions;
     Target     = target;
 }
Beispiel #10
0
 public NewArrayAction(CalculatedValue target, TypeReference type, JavaValue count)
 {
     Target = target;
     Type   = type;
     Count  = count;
 }
Beispiel #11
0
 public ConstantSetAction(CalculatedValue target, JavaValue value)
 {
     Target = target;
     Value  = value;
 }
Beispiel #12
0
 public UnaryOperationAction(CalculatedValue target, Op operation, JavaValue value)
 {
     Target    = target ?? throw new ArgumentNullException(nameof(target));
     Operation = operation;
     Value     = value ?? throw new ArgumentNullException(nameof(value));
 }
Beispiel #13
0
 public ArrayLengthAction(CalculatedValue target, JavaValue array)
 {
     Target = target;
     Array  = array;
 }