示例#1
0
        public bool DetectSwitch_GenerateSwitch(IList <ILNode> body, ILBasicBlock head, int pos)
        {
            ILExpression condition;
            ILLabel      trueLabel;
            ILLabel      fallThough;

            // REMEMBER:  The searching goes backwards, so we find the FIRST case here, so here is the problem
            // Evey time we run this, we have to search for the first block of the case statement backwards and if
            // the push var is not resolved, we have to drop out... evey single time till the push IS resolved
            // so be sure to run this at the bottom of the decision chain.  Its fine if the push is a simple var
            // but I can bet cash this runs 2-3 times if the push is some kind of expression like 5 + (3 % switch_var))
            // we could change the way the optimizing loop works by going from the start and building a que of things
            // to remove, delete or change hummm...  Take longer but it would make building this functions MUCH simpler
            if (MatchSwitchCase(head, out trueLabel, out fallThough, out condition) &&
                !MatchSwitchCase(body.ElementAtOrDefault(pos - 1) as ILBasicBlock, out trueLabel, out fallThough, out condition)
                )  // && head.MatchLastAt(6, GMCode.Push,out switch_expr))
            {
                List <ILBasicBlock> caseBlocks = GetAllCaseBlocks(body, head, pos, out condition, out fallThough);
                if (caseBlocks == null)
                {
                    return(false);
                }
                ILExpression fswitch = new ILExpression(GMCode.Switch, null);
                FakeSwitch   args    = new FakeSwitch();
                args.SwitchExpression = condition;
                args.CaseExpressions  = caseBlocks.Select(bb =>
                                                          new KeyValuePair <ILExpression, ILLabel>((bb.ElementAtLast(3) as ILExpression).Arguments[0], (bb.ElementAtLast(1) as ILExpression).Operand as ILLabel)
                                                          ).ToList();

                fswitch.Operand = args;
                // search the blocks for ending popz's and remove the popz
                HashSet <ILBasicBlock> blocks_done = new HashSet <ILBasicBlock>();
                Stack <ILBasicBlock>   agenda      = new Stack <ILBasicBlock>(caseBlocks);
                while (agenda.Count > 0)
                {
                    ILBasicBlock bb = agenda.Pop();
                    if (blocks_done.Contains(bb))
                    {
                        continue;                           // already did it
                    }
                    ILExpression popz = bb.Body.OfType <ILExpression>().Where(e => e.Code == GMCode.Popz).SingleOrDefault();
                    if (popz != null)
                    {
                        bb.Body.Remove(popz); // remove it
                    }
                    else
                    {
                        ILLabel exit = bb.OperandLabelLastAt(0);
                        if (exit != null && !blocks_done.Contains(labelToBasicBlock[exit]))
                        {
                            agenda.Push(labelToBasicBlock[exit]);
                        }
                        exit = bb.OperandLabelLastAt(1); // check if we have a bt or something
                        if (exit != null && !blocks_done.Contains(labelToBasicBlock[exit]))
                        {
                            agenda.Push(labelToBasicBlock[exit]);
                        }
                    }
                    blocks_done.Add(bb);
                }
                ILBasicBlock startOfAllCases = caseBlocks.First();
                caseBlocks.Remove(startOfAllCases);
                startOfAllCases.Body.RemoveTail(GMCode.Dup, GMCode.Push, GMCode.Seq, GMCode.Bt, GMCode.B);
                startOfAllCases.Body.Add(fswitch);
                startOfAllCases.Body.Add(new ILExpression(GMCode.B, fallThough)); //  end_of_switch.EntryLabel()));
                body.RemoveAll(caseBlocks);

                return(true);
            }


            return(false);
        }
示例#2
0
        public bool DetectSwitchAndConvertToBranches(IList <ILNode> body, ILBasicBlock head, int pos)
        {
            ILExpression condition;
            ILLabel      trueLabel;
            ILLabel      fallThough;

            // REMEMBER:  The searching goes backwards, so we find the LAST case here, so here is the problem
            // Evey time we run this, we have to search for the first block of the case statement backwards and if
            // the push var is not resolved, we have to drop out... evey single time till the push IS resolved
            // so be sure to run this at the bottom of the decision chain.  Its fine if the push is a simple var
            // but I can bet cash this runs 2-3 times if the push is some kind of expression like 5 + (3 % switch_var))
            // we could change the way the optimizing loop works by going from the start and building a que of things
            // to remove, delete or change hummm...  Take longer but it would make building this functions MUCH simpler
            if (MatchSwitchCase(head, out trueLabel, out fallThough, out condition))  // && head.MatchLastAt(6, GMCode.Push,out switch_expr))
            {
                List <ILBasicBlock> caseBlocks = GetAllCaseBlocks(body, head, pos, out condition, out fallThough);

                foreach (var bb in caseBlocks) // replace the dup statements
                {
                    Debug.Assert(bb.MatchLastAt(5, GMCode.Dup));
                    bb.Body[bb.Body.Count - 5] = new ILExpression(GMCode.Push, null, condition);
                    ILExpression expr = bb.Body[bb.Body.Count - 3] as ILExpression;
                    //   expr.Code = GMCode.Case; // conver the equals to a case
                }
                // search the blocks for ending popz's
                HashSet <ILBasicBlock> blocks_done = new HashSet <ILBasicBlock>();
                Stack <ILBasicBlock>   agenda      = new Stack <ILBasicBlock>(caseBlocks);
                while (agenda.Count > 0)
                {
                    ILBasicBlock bb = agenda.Pop();
                    if (blocks_done.Contains(bb))
                    {
                        continue;                           // already did it
                    }
                    ILExpression popz = bb.Body.OfType <ILExpression>().Where(e => e.Code == GMCode.Popz).SingleOrDefault();
                    if (popz != null)
                    {
                        bb.Body.Remove(popz); // remove it
                        blocks_done.Add(bb);
                    }
                    else
                    {
                        ILLabel exit = bb.OperandLabelLastAt(0);
                        if (exit != null && !blocks_done.Contains(labelToBasicBlock[exit]))
                        {
                            agenda.Push(labelToBasicBlock[exit]);
                        }
                        exit = bb.OperandLabelLastAt(1); // check if we have a bt or something
                        if (exit != null && !blocks_done.Contains(labelToBasicBlock[exit]))
                        {
                            agenda.Push(labelToBasicBlock[exit]);
                        }
                    }
                }


                return(true);
            }


            return(false);
        }