Exemple #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;
                }

                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);
        }
Exemple #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);

            if (!pushedArgs.CanAddMore)
            {
                return(pushedArgs);
            }

            Dictionary <int, Branch> branches = null;
            var states      = new Stack <State>();
            var state       = new State(index, null, 0, 0, 1, new HashSet <int>());
            var isBacktrack = false;

            states.Push(state.Clone());
            while (true)
            {
                while (state.index >= 0)
                {
                    if (branches != null && branches.TryGetValue(state.index, out var branch) && state.visited.Add(state.index))
                    {
                        branch.current = 0;
                        var brState = state.Clone();
                        brState.branch = branch;
                        states.Push(brState);
                    }
                    if (!isBacktrack)
                    {
                        state.index--;
                    }
                    isBacktrack = false;
                    var update = UpdateState(instructions, state, pushedArgs);
                    if (update == Update.Finish)
                    {
                        return(pushedArgs);
                    }
                    if (update == Update.Fail)
                    {
                        break;
                    }
                }

                if (states.Count == 0)
                {
                    return(pushedArgs);
                }

                var prevValidArgs = state.validArgs;
                state = states.Pop();
                if (state.validArgs < prevValidArgs)
                {
                    for (int i = state.validArgs + 1; i <= prevValidArgs; i++)
                    {
                        pushedArgs.Pop();
                    }
                }

                if (branches == null)
                {
                    branches = GetBranches(instructions);
                }
                else
                {
                    isBacktrack = true;
                    state.index = state.branch.Variants[state.branch.current++];
                    if (state.branch.current < state.branch.Variants.Count)
                    {
                        states.Push(state.Clone());
                    }
                    else
                    {
                        state.branch = null;
                    }
                }
            }
        }
        // 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;
        }
Exemple #4
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);
        }