Ejemplo n.º 1
0
        public static ILLabel GotoLabel(this ILBasicBlock bb)
        {
            if (bb.MatchLastAt(1, GMCode.Ret) || bb.MatchLastAt(1, GMCode.Exit))
            {
                return(null);
            }
            ILLabel label = (bb.Body[bb.Body.Count - 1] as ILExpression).Operand as ILLabel;

            Debug.Assert(label != null);
            return(label);
        }
Ejemplo n.º 2
0
        // Detect a switch block, combine them all, and either build a switch block or
        // just a bunch of if statements
        // the trick is to get rid of the popv at the end of all these case statements
        // might just have to be removed with the "remove redudent code" system

        bool MatchSwitchCase(ILBasicBlock head, out ILLabel trueLabel, out ILLabel falseLabel, out ILExpression condition)
        {
            if (head != null &&
                head.MatchLastAndBr(GMCode.Bt, out trueLabel, out falseLabel) &&
                head.MatchLastAt(3, GMCode.Seq) &&
                head.MatchLastAt(4, GMCode.Push, out condition) &&
                head.MatchLastAt(5, GMCode.Dup))
            {
                return(true);
            }
            trueLabel  = default(ILLabel);
            falseLabel = default(ILLabel);
            condition  = default(ILExpression);
            return(false);
        }
Ejemplo n.º 3
0
        public List <ILBasicBlock> GetAllCaseBlocks(IList <ILNode> body, ILBasicBlock head, int pos, out ILExpression condition, out ILLabel fallout)
        {
            ILExpression        fswitch    = new ILExpression(GMCode.Switch, null);
            List <ILBasicBlock> caseBlocks = new List <ILBasicBlock>();
            int     swtichStart            = pos;
            ILLabel trueLabel;
            ILLabel falseLabel;

            while (MatchSwitchCase(head, out trueLabel, out falseLabel, out condition))
            {
                caseBlocks.Add(head);
                head = body.ElementAtOrDefault(++swtichStart) as ILBasicBlock;
            }
            ILBasicBlock switchHead = caseBlocks.First();

            if (!switchHead.ElementAtLastOrDefault(5).isNodeResolved())
            {
                fallout = null; condition = null; return(null);
            }
            //   caseBlocks.Reverse(); // reverse the order so its correct
            Debug.Assert(switchHead.MatchLastAt(6, GMCode.Push, out condition)); // return false;
            switchHead.RemoveAt(switchHead.Body.Count - 6);                      // ugh, might have to change the matchLastAt
            fallout = caseBlocks.Last().OperandLabelLastAt(0);
            return(caseBlocks);
        }
Ejemplo n.º 4
0
        // This is before the expression is processed, so ILValue's and constants havn't been assigned

        public bool SimplifyTernaryOperator(IList <ILNode> body, ILBasicBlock head, int pos)
        {
            Debug.Assert(body.Contains(head));
            //    Debug.Assert((head.Body[0] as ILLabel).Name != "Block_54");
            //     Debug.Assert((head.Body[0] as ILLabel).Name != "L1257");
            ILExpression condExpr;
            ILLabel      trueLabel;
            ILLabel      falseLabel;

            ILExpression trueExpr;
            ILLabel      trueFall;

            ILExpression falseExpr;
            ILLabel      falseFall;


            ILLabel finalFalseFall;
            ILLabel finalTrueFall;

            if (head.MatchLastAndBr(GMCode.Bt, out trueLabel, out condExpr, out falseLabel) &&
                labelGlobalRefCount[trueLabel] == 1 &&
                labelGlobalRefCount[falseLabel] == 1 &&
                labelToBasicBlock[trueLabel].MatchSingleAndBr(GMCode.Push, out trueExpr, out trueFall) &&
                labelToBasicBlock[falseLabel].MatchSingleAndBr(GMCode.Push, out falseExpr, out falseFall) &&
                trueFall == falseFall &&
                body.Contains(labelToBasicBlock[trueFall])
                // finalFall.Code == GMCode.Pop
                ) // (finalFall == null || finalFall.Code == GMCode.Pop)
            {
                ILBasicBlock trueBlock  = labelToBasicBlock[trueLabel];
                ILBasicBlock falseBlock = labelToBasicBlock[falseLabel];
                ILBasicBlock fallBlock  = labelToBasicBlock[trueFall];
                ILExpression newExpr    = ResolveTernaryExpression(condExpr, trueExpr, falseExpr);

                head.Body.RemoveTail(GMCode.Bt, GMCode.B);
                body.RemoveOrThrow(trueBlock);
                body.RemoveOrThrow(falseBlock);
                IList <ILExpression> finalFall;
                // figure out if its a wierd short or not
                if (fallBlock.MatchSingleAndBr(GMCode.Bt, out finalTrueFall, out finalFall, out finalFalseFall) &&
                    finalFall.Count == 0)
                {
                    head.Body.Add(new ILExpression(GMCode.Bt, finalTrueFall, newExpr));
                    if (labelGlobalRefCount[trueFall] == 2)
                    {
                        body.RemoveOrThrow(fallBlock);
                    }
                }
                else if (fallBlock.Body.Count == 2)  // wierd break,
                {
                    finalFalseFall = fallBlock.GotoLabel();
                    head.Body.Add(new ILExpression(GMCode.Push, null, newExpr)); // we want to push it for next pass
                    if (labelGlobalRefCount[trueFall] == 2)
                    {
                        body.RemoveOrThrow(fallBlock);
                    }
                }
                else if (fallBlock.MatchAt(1, GMCode.Pop))  // generated? wierd instance?
                {
                    finalFalseFall = fallBlock.EntryLabel();
                    error.Info("Wierd Generated Pop here", newExpr);
                    head.Body.Add(new ILExpression(GMCode.Push, null, newExpr));
                    // It should be combined in JoinBasicBlocks function
                    // so don't remove failblock
                }
                else if (fallBlock.MatchAt(1, GMCode.Assign, out finalFall)) // This is an assignment case and unsure what its for
                {
                    finalFall.Add(newExpr);
                    finalFalseFall = fallBlock.EntryLabel();
                }
                if (finalFalseFall == null && fallBlock.MatchLastAt(1, GMCode.Ret))
                {
                    head.Body.Add(new ILExpression(GMCode.Ret, null));
                }
                else
                {
                    Debug.Assert(finalFalseFall != null);
                    head.Body.Add(new ILExpression(GMCode.B, finalFalseFall));
                }
                return(true);
            }
            return(false);
        }
Ejemplo n.º 5
0
        public bool MatchRepeatStructure(IList <ILNode> body, ILBasicBlock head, int pos)
        {
            ILExpression rcount;
            ILExpression pushZero;
            int          dupMode = 0;
            ILLabel      fallthough;
            ILLabel      repeatBlock;

            if (head.MatchLastAt(6, GMCode.Push, out rcount) && // header for a repeat, sets it up
                head.MatchLastAt(5, GMCode.Dup, out dupMode) &&
                head.MatchLastAt(4, GMCode.Push, out pushZero) &&
                pushZero.Code == GMCode.Constant && (pushZero.Operand as ILValue).IntValue == 0 &&
                head.MatchLastAt(3, GMCode.Sle) &&
                head.MatchLastAndBr(GMCode.Bt, out fallthough, out repeatBlock))
            {
                // We have to seeperate the head from other bits of the block
                // humm, mabye have to put this in the general build routine like we did with push V:(
                head.Body.RemoveTail(GMCode.Push, GMCode.Dup, GMCode.Push, GMCode.Sle, GMCode.Bt, GMCode.B);

                ILBasicBlock header_block;
                ILLabel      header_label;
                if (head.Body.Count == 1)
                {// The head only has the label, so its safe to use this as the header
                    header_block = head;
                    header_label = head.EntryLabel();
                }
                else
                {
                    header_label = ILLabel.Generate("R");
                    // We have to seperate the head.
                    header_block = new ILBasicBlock();
                    head.Body.Add(new ILExpression(GMCode.B, header_label));
                    header_block.Body.Add(header_label);
                    body.Insert(pos + 1, header_block); // insert before the block so it looks in order
                }

                header_block.Body.Add(new ILExpression(GMCode.Repeat, repeatBlock, rcount));
                header_block.Body.Add(new ILExpression(GMCode.B, fallthough));

                // NOW we got to find the block that matches

                ILExpression subOneConstant;
                ILLabel      footerContinue, footerfallThough;

                /*
                 *
                 *
                 * while (!(start.MatchLastAt(5, GMCode.Push, out subOneConstant) &&
                 *   subOneConstant.Code == GMCode.Constant && (subOneConstant.Operand as ILValue).IntValue == 1 &&
                 *   start.MatchLastAt(4, GMCode.Sub) &&
                 *   start.MatchLastAt(3, GMCode.Dup, out dupMode) && dupMode == 0 &&
                 *  start.MatchLastAndBr(GMCode.Bt, out footerContinue, out footerfallThough)))
                 * {
                 *  ILLabel next = start.GotoLabel();
                 *  start = labelToBasicBlock[next];
                 * }
                 */// ok, on more complicated stuf like an internal loop, this f***s up, so we are going to do a hack
                // The popz fallthough comes RIGHT after the decrment for the repeate loop, so we are going to move up one from that
                // then check it
                ILBasicBlock popzBlock = labelToBasicBlock[fallthough]; //
                Debug.Assert((popzBlock.Body[1] as ILExpression).Code == GMCode.Popz);
                popzBlock.Body.RemoveAt(1);                             // remove the popz
                ILBasicBlock footer = body[body.IndexOf(popzBlock) - 1] as ILBasicBlock;

                if (footer.MatchLastAt(5, GMCode.Push, out subOneConstant) &&
                    subOneConstant.Code == GMCode.Constant && (subOneConstant.Operand as ILValue).IntValue == 1 &&
                    footer.MatchLastAt(4, GMCode.Sub) &&
                    footer.MatchLastAt(3, GMCode.Dup, out dupMode) && dupMode == 0 &&
                    footer.MatchLastAndBr(GMCode.Bt, out footerContinue, out footerfallThough))
                {
                    Debug.Assert(footerfallThough == fallthough && repeatBlock == footerContinue); // sanity check
                    footer.Body.RemoveTail(GMCode.Push, GMCode.Sub, GMCode.Dup, GMCode.Bt, GMCode.B);
                    footer.Body.Add(new ILExpression(GMCode.B, header_block.EntryLabel()));
                }
                else
                {
                    throw new Exception("F**k me");
                }


                // Found!  Some sanity checks thogh

                /* MAJOR BUG UNFINSHED WORK ALERT!
                 * Ok, so this isn't used in undertale, but at some point, somone might want to do a break or continue
                 * Inside of a repeat statment.  I have NO clue why though, use a while?
                 * Anyway, if thats the case then you MUST change the target label of evetyhing going to start, to fallthough, otherwise
                 * the goto cleaner will start screaming at you and do alot of weird stuff
                 * fyi, like the with statments, I am converting this thing into a while loop so I don't have to have
                 * custom loop graph code for these things
                 * So, for now? convert start to loop back to head, head jumps to fallthough, and we remove the popz from the fall though
                 */
                //   ILLabel.Generate("Block_", nextLabelIndex++);



                return(true);
            }
            return(false);
        }