예제 #1
0
		// 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;
		}
예제 #2
0
        // 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);
        }
예제 #3
0
        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);
        }