// May not return all args. The args are returned in reverse order. static PushedArgs GetPushedArgInstructions(IList<Instruction> instructions, int index, int numArgs) { var pushedArgs = new PushedArgs(numArgs); Instruction instr; int skipPushes = 0; while (index >= 0 && pushedArgs.CanAddMore) { instr = GetPreviousInstruction(instructions, ref index); if (instr == null) break; int pushes, pops; instr.CalculateStackUsage(false, out pushes, out pops); if (pops == -1) break; if (instr.OpCode.Code == Code.Dup) { pushes = 1; pops = 0; } if (pushes > 1) break; if (skipPushes > 0) { skipPushes -= pushes; if (skipPushes < 0) break; skipPushes += pops; } else { if (pushes == 1) pushedArgs.Add(instr); skipPushes += pops; } } instr = pushedArgs.Get(0); if (instr != null && instr.OpCode.Code == Code.Dup) { instr = GetPreviousInstruction(instructions, ref index); if (instr != null) { int pushes, pops; instr.CalculateStackUsage(false, out pushes, out pops); if (pushes == 1 && pops == 0) pushedArgs.Set(0, instr); } } pushedArgs.FixDups(); return pushedArgs; }
// May not return all args. The args are returned in reverse order. static PushedArgs GetPushedArgInstructions(IList <Instruction> instructions, int index, int numArgs) { var pushedArgs = new PushedArgs(numArgs); Instruction instr; int skipPushes = 0; while (index >= 0 && pushedArgs.CanAddMore) { instr = GetPreviousInstruction(instructions, ref index); if (instr == null) { break; } instr.CalculateStackUsage(false, out int pushes, out int pops); if (pops == -1) { break; } if (instr.OpCode.Code == Code.Dup) { pushes = 1; pops = 0; } if (pushes > 1) { break; } if (skipPushes > 0) { skipPushes -= pushes; if (skipPushes < 0) { break; } skipPushes += pops; } else { if (pushes == 1) { pushedArgs.Add(instr); } skipPushes += pops; } } instr = pushedArgs.Get(0); if (instr != null && instr.OpCode.Code == Code.Dup) { instr = GetPreviousInstruction(instructions, ref index); if (instr != null) { instr.CalculateStackUsage(false, out int pushes, out int pops); if (pushes == 1 && pops == 0) { pushedArgs.Set(0, instr); } } } pushedArgs.FixDups(); return(pushedArgs); }
private static Update UpdateState(IList <Instruction> instructions, State state, PushedArgs pushedArgs) { if (state.index < 0 || state.index >= instructions.Count) { return(Update.Fail); } var instr = instructions[state.index]; if (!Instr.IsFallThrough(instr.OpCode)) { return(Update.Fail); } instr.CalculateStackUsage(false, out int pushes, out int pops); if (pops == -1) { return(Update.Fail); } var isDup = instr.OpCode.Code == Code.Dup; if (isDup) { pushes = 1; pops = 0; } if (pushes > 1) { return(Update.Fail); } if (state.skipPushes > 0) { state.skipPushes -= pushes; if (state.skipPushes < 0) { return(Update.Fail); } state.skipPushes += pops; } else { if (pushes == 1) { if (isDup) { state.addPushes++; } else { for (; state.addPushes > 0; state.addPushes--) { pushedArgs.Add(instr); state.validArgs++; if (!pushedArgs.CanAddMore) { return(Update.Finish); } } state.addPushes = 1; } } state.skipPushes += pops; } return(Update.Ok); }