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"); } }
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); }