// устранение переходов через переходы (пример из презентации Opt5.pdf слайд 32)
        public static (bool wasChanged, IReadOnlyList <Instruction> instructions) RemoveGotoThroughGoto(IReadOnlyList <Instruction> instructions)
        {
            if (instructions is null)
            {
                throw new ArgumentNullException("instructions is null");
            }

            var wasChanged      = false;
            var newInstructions = new List <Instruction>();

            for (var i = 0; i < instructions.Count; ++i)
            {
                if (instructions[i].Operation == "ifgoto" && 4 <= (instructions.Count - i))
                {
                    var com0 = instructions[i];
                    var com1 = instructions[i + 1];
                    var com2 = instructions[i + 2];
                    var com3 = instructions[i + 3];

                    // только одна операция
                    if (com1.Operation == "goto" && com1.Label == "" && com2.Operation != "noop" && com0.Argument2 == com2.Label && com1.Argument1 == com3.Label)
                    {
                        var tmpName = ThreeAddressCodeTmp.GenTmpName();
                        newInstructions.Add(new Instruction(com0.Label, "NOT", com0.Argument1, "", tmpName));
                        newInstructions.Add(new Instruction("", "ifgoto", tmpName, com3.Label, ""));

                        var label = com2.Label.StartsWith("L") && uint.TryParse(com2.Label.Substring(1), out _) ? "" : com2.Label;
                        newInstructions.Add(new Instruction(label, com2.Operation, com2.Argument1, com2.Argument2, com2.Result));
                        newInstructions.Add(com3.Copy());

                        wasChanged = true;
                        i         += 3;
                        continue;
                    }
                }
                newInstructions.Add(instructions[i].Copy());
            }
            return(wasChanged, newInstructions);
        }
コード例 #2
0
        // устранение переходов через переходы (experimental)
        #region

        /*public static Tuple<bool, List<Instruction>> RemoveGotoThroughGoto(List<Instruction> instructions)
         * {
         *  if (instructions is null)
         *      throw new ArgumentNullException("instructions is null");
         *
         *  bool isChange = false;
         *  var newInstructions = new List<Instruction>();
         *
         *  for (int i = 0; i < instructions.Count; ++i)
         *  {
         *      var com0 = instructions[i];
         *      if (instructions[i].Operation == "ifgoto" && 4 <= (instructions.Count - i))
         *      {
         *          var com1 = instructions[i + 1];
         *          var com2 = instructions[i + 2];
         *
         *          //
         *          if (com1.Operation == "goto" && com1.Label == "" && com2.Operation != "noop" && com0.Argument2 == com2.Label)
         *          {
         *              // search end label with "noop" operation
         *              var endLabelIndex = FindLabelIndex(instructions, i + 2, com1.Argument1);
         *              if (0 < endLabelIndex || endLabelIndex < instructions.Count || instructions[endLabelIndex].Operation == "noop")
         *              {
         *                  //
         *                  string tmpName = ThreeAddressCodeTmp.GenTmpName();
         *                  newInstructions.Add(new Instruction(com0.Label, "EQUAL", "False", com0.Argument1, tmpName)); // операция отрицания через EQUAL
         *                  newInstructions.Add(new Instruction("", "ifgoto", tmpName, com1.Argument1, ""));
         *
         *                  // copy instructions for true branch
         *                  newInstructions.Add(new Instruction("", com2.Operation, com2.Argument1, com2.Argument2, com2.Result));
         *                  for (int k = i + 3; k < endLabelIndex; ++k)
         *                  {
         *                      var bla = instructions[k];
         *                      newInstructions.Add(new Instruction(bla.Label, bla.Operation, bla.Argument1, bla.Argument2, bla.Result));
         *                  }
         *
         *                  var endLabel = instructions[endLabelIndex];
         *                  newInstructions.Add(new Instruction(endLabel.Label, endLabel.Operation, endLabel.Argument1, endLabel.Argument2, endLabel.Result));
         *                  i = endLabelIndex;
         *                  isChange = true;
         *                  continue;
         *              }
         *          }
         *      }
         *
         *      newInstructions.Add(new Instruction(com0.Label, com0.Operation, com0.Argument1, com0.Argument2, com0.Result));
         *  }
         *
         *  return Tuple.Create(isChange, newInstructions);
         * }*/

        #endregion

        // устранение переходов через переходы (пример из презентации Opt5.pdf слайд 32)
        public static Tuple <bool, List <Instruction> > RemoveGotoThroughGoto(List <Instruction> instructions)
        {
            if (instructions is null)
            {
                throw new ArgumentNullException("instructions is null");
            }

            bool isChange        = false;
            var  newInstructions = new List <Instruction>();

            for (int i = 0; i < instructions.Count; ++i)
            {
                if (instructions[i].Operation == "ifgoto" && 4 <= (instructions.Count - i))
                {
                    var com0 = instructions[i];
                    var com1 = instructions[i + 1];
                    var com2 = instructions[i + 2];
                    var com3 = instructions[i + 3];

                    // только одна операция
                    if (com1.Operation == "goto" && com1.Label == "" && com2.Operation != "noop" && com0.Argument2 == com2.Label && com1.Argument1 == com3.Label)
                    {
                        string tmpName = ThreeAddressCodeTmp.GenTmpName();
                        newInstructions.Add(new Instruction(com0.Label, "NOT", com0.Argument1, "", tmpName));
                        newInstructions.Add(new Instruction("", "ifgoto", tmpName, com3.Label, ""));
                        newInstructions.Add(new Instruction("", com2.Operation, com2.Argument1, com2.Argument2, com2.Result));
                        newInstructions.Add(new Instruction(com3.Label, com3.Operation, com3.Argument1, com3.Argument2, com3.Result));

                        isChange = true;
                        i       += 3;
                        continue;
                    }
                }
                newInstructions.Add(new Instruction(instructions[i].Label, instructions[i].Operation, instructions[i].Argument1, instructions[i].Argument2, instructions[i].Result));
            }
            return(Tuple.Create(isChange, newInstructions));
        }