Beispiel #1
0
        void ProcessExpressions(List <ILNode> body, ILBasicBlock head, int pos)
        {
            Stack <ILNode> stack = new Stack <ILNode>();
            List <ILNode>  list  = new List <ILNode>();

            Dup1Seen = false;
            TestAndFixWierdLoop(body, head, pos);


            for (int i = 0; i < head.Body.Count; i++)
            {
                if (stack.Count == 1 &&
                    head.MatchAt(i, GMCode.Dup) &&
                    head.MatchAt(i + 1, GMCode.Push) &&
                    head.MatchAt(i + 2, GMCode.Seq) &&
                    head.MatchAt(i + 3, GMCode.Bt))
                {
                    CreateSwitchExpresion(stack.Pop(), list, body, head, pos);


                    break; // we are done with this block
                }
                else
                {
                    Status s = ProcessExpression(list, head, i, stack);
                }
            }
            head.Body = list;
        }
Beispiel #2
0
        void TestAndFixWierdLoop(List <ILNode> body, ILBasicBlock head, int pos)
        {
            object       uvalue1;
            ILValue      value2;
            ILLabel      endLoop;
            ILLabel      startLoop;
            ILExpression filler;
            //Debug.Assert((head.Body[0] as ILLabel).Name != "L36");
            // Wierd one here.  I ran accross this a few times and I think this is generated code
            // for events.  Basicly, it pushes a constant on the stack and uses a repeat loop
            // however since I am not doing ANY kind of real stack/temporary analysis.  I would have
            // to rewrite and add a bunch of code to get that to work and right now its only a few functions
            // Its easyer to build a while loop out of it and let the decompiler handle it rather than
            // build a more robust stack anilizer
            // ugh have to make a new block for it too, meh
            int headLen = head.Body.Count;

            if (head.MatchAt(headLen - 6, GMCode.Push, out uvalue1) &&
                head.MatchAt(headLen - 5, GMCode.Dup) &&
                head.MatchAt(headLen - 4, GMCode.Push, out value2) &&

                head.MatchAt(headLen - 3, GMCode.Sle) &&
                head.MatchLastAndBr(GMCode.Bt, out endLoop, out filler, out startLoop))
            {
                // ok, lets rewrite the head so it makes sence
                ILLabel       newLoopStart = NewJunkLoop();
                ILVariable    genVar       = NewGeneratedVar();
                List <ILNode> newHead      = new List <ILNode>();
                for (int ii = 0; ii <= headLen - 7; ii++)
                {
                    newHead.Add(head.Body[ii]);                                       // add the front of it including the sub part
                }
                newHead.Add(new ILExpression(GMCode.Push, uvalue1));
                newHead.Add(new ILExpression(GMCode.Pop, genVar));
                newHead.Add(new ILExpression(GMCode.B, newLoopStart));
                ILBasicBlock newLoopBlock = new ILBasicBlock();
                newLoopBlock.Body.Add(newLoopStart);
                newLoopBlock.Body.Add(new ILExpression(GMCode.Push, genVar));
                newLoopBlock.Body.Add(new ILExpression(GMCode.Push, new ILValue(0)));

                newLoopBlock.Body.Add(new ILExpression(GMCode.Sgt, null));
                newLoopBlock.Body.Add(new ILExpression(GMCode.Bf, endLoop, new ILExpression(GMCode.Pop, null)));
                newLoopBlock.Body.Add(new ILExpression(GMCode.B, startLoop));
                head.Body = newHead;
                body.Add(newLoopBlock);
                // Now the hard part, we have to find the end bit
                for (int j = pos; j < body.Count; j++)
                {
                    ILBasicBlock bj = body[j] as ILBasicBlock;
                    ILLabel      testEnd, testStart;
                    ILValue      subPart;
                    int          len = bj.Body.Count;
                    //    Debug.Assert((bj.Body[0] as ILLabel).Name != "L114");
                    if (bj.MatchLastAndBr(GMCode.Bt, out testStart, out filler, out testEnd) &&
                        testEnd == endLoop && testStart == startLoop &&
                        bj.MatchAt(len - 3, GMCode.Dup) &&
                        bj.MatchAt(len - 4, GMCode.Sub) &&
                        bj.MatchAt(len - 5, GMCode.Push, out subPart)
                        )
                    {
                        List <ILNode> list2 = new List <ILNode>();
                        for (int ii = 0; ii <= len - 6; ii++)
                        {
                            list2.Add(bj.Body[ii]);                                   // add the front of it including the sub part
                        }
                        list2.Add(new ILExpression(GMCode.Push, genVar));
                        list2.Add(bj.Body[len - 5]);                         // add the sub part
                        list2.Add(bj.Body[len - 4]);                         // add the sub part
                        list2.Add(new ILExpression(GMCode.Pop, genVar));     // assign it
                        list2.Add(new ILExpression(GMCode.B, newLoopStart)); // branch back to the start
                        bj.Body = list2;                                     // replace
                        break;                                               // all done, let it continue
                    }
                }
                //  Debug.Assert(false); // coudln't find the end block
            }
        }
Beispiel #3
0
        void CreateSwitchExpresion(ILNode condition, List <ILNode> list, List <ILNode> body, ILBasicBlock head, int pos)
        {
            // we are in a case block, check if its the first block

            List <ILBasicBlock> caseBlocks       = new List <ILBasicBlock>();
            List <ILLabel>      caseLabels       = new List <ILLabel>();
            ILExpression        switchExpression = new ILExpression(GMCode.Switch, null);

            switchExpression.Arguments.Add(NodeToExpresion(condition)); // pop the switch condition
            ILBasicBlock current = head;
            ILLabel      nextCase;
            ILLabel      caseTrue;
            ILExpression fakeArgument;

            while (current.MatchLastAndBr(GMCode.Bt, out caseTrue, out fakeArgument, out nextCase))
            {
                ILNode operand;
                if (!current.MatchAt(current.Body.Count - 4, GMCode.Push, out operand))
                {
                    throw new Exception("fix");
                }
                if (!(operand is ILValue))
                {
                    throw new Exception("Can only handle constants right now");
                }
                switchExpression.Arguments.Add(new ILExpression(GMCode.Case, caseTrue, NodeToExpresion(operand)));
                caseLabels.Add(caseTrue);
                body.Remove(current);
                current = labelToBasicBlock[nextCase];
            }
            body.Insert(pos, head);

            var lastBlock = current;


            ILLabel fallLabel;

            if (!lastBlock.MatchSingle(GMCode.B, out fallLabel))
            {
                throw new Exception("fix");
            }
            current = labelToBasicBlock[fallLabel];
            if (!current.MatchAt(1, GMCode.Popz))
            { // has a default case
              // Side note, the LoopAndConditions figures out if we have a default case by checking
              // if the ending branch is linked to all the other case branches
              // so we don't need to do anything here
              // All this code is JUST for finding that popz that pops the condition out of the switch
              // if you don't care about it, you could just search though all the expresions and remove any and all
              // popz's  I am beggining to think this is the right way to do it as I don't see any other uses
              // of popz's
              //  Debug.Assert(false);
                BuildNextBlockData(); // build block chain, we need this for default and mabye case lookups
                                      // ok, this is why we DON'T want to remove redundent code as there is this empty
                                      // useless goto RIGHt after this that has the link to the finale case
                ILLabel nextBlockLabel = lastBlock.Body.First() as ILLabel;
                var     uselessBlock   = this.labelToNextBlock[nextBlockLabel];
                ILLabel newFallLabel;
                if (!uselessBlock.MatchSingle(GMCode.B, out newFallLabel))
                {
                    throw new Exception("fix");
                }
                current = labelToBasicBlock[newFallLabel];

                if (!current.MatchAt(1, GMCode.Popz))
                {
                    throw new Exception("I have no idea where the popz is for this switch");
                }
            }
            current.Body.RemoveAt(1);
            ILLabel lastBlockLabel = lastBlock.Body.First() as ILLabel;

            if (this.labelGlobalRefCount[lastBlockLabel] == 1)
            {
                body.Remove(lastBlockLabel);
            }
            switchExpression.Operand = caseLabels.ToArray();

            list.Add(switchExpression);
            list.Add(new ILExpression(GMCode.B, fallLabel));
        }