/// <summary>
        /// Протянуть if с метками
        /// </summary>
        /// <param name="findInstruction">Инструкция, которую мы ищем</param>
        /// <param name="instructions">Набор наших инструкций</param>
        /// <returns>
        /// Вернёт изменённые инструкции, если меток if не более двух
        /// </returns>
        private static List <Instruction> PropagateIfWithLabel(Instruction findInstruction, List <Instruction> instructions)
        {
            var findIndexIf = instructions.IndexOf(findInstruction);

            if (findIndexIf == -1 ||
                instructions.Where(x => instructions[findIndexIf].Label == x.Argument1 && x.Operation == "goto" && x.ToString() != instructions[findIndexIf].ToString()).Count() > 1)
            {
                return(instructions);
            }

            var findItem = instructions.Where(x => instructions[findIndexIf].Label == x.Argument1 && x.Operation == "goto").Count() > 0 ?
                           instructions.Where(x => instructions[findIndexIf].Label == x.Argument1 && x.Operation == "goto").ElementAt(0) :
                           new Instruction("", "", "", "", "");
            var findIndexGoto = instructions.IndexOf(findItem);

            if (findIndexGoto == -1)
            {
                return(instructions);
            }

            wasChanged = true;
            instructions[findIndexGoto] = new Instruction("", instructions[findIndexIf].Operation, instructions[findIndexIf].Argument1, instructions[findIndexIf].Argument2, instructions[findIndexIf].Result);
            instructions.RemoveAt(findIndexIf);
            if (instructions[findIndexIf].Label == "")
            {
                instructions[findIndexIf].Label = ThreeAddressCodeTmp.GenTmpLabel();
            }
            instructions.Insert(findIndexGoto + 1, new Instruction("", "goto", instructions[findIndexIf].Label, "", ""));

            return(instructions);
        }
Пример #2
0
        /// <summary>
        /// Протянуть if с метками
        /// </summary>
        /// <param name="findInstruction">Инструкция которую мы ищем</param>
        /// <param name="instructions">Набор наших инструкций</param>
        /// <returns>
        /// Вернет измененные инструкции если меткок if не более двух
        /// </returns>
        private static List <Instruction> StretchIFWithLabel(Instruction findInstruction, List <Instruction> instructions)
        {
            int findIndexIf = instructions.IndexOf(findInstruction);

            if (findIndexIf == -1 ||
                instructions.Where(x => instructions[findIndexIf].Label == x.Argument1 && x.Operation == "goto" && x.ToString() != instructions[findIndexIf].ToString()).Count() > 1)
            {
                return(instructions);
            }

            int findIndexGoto = instructions.IndexOf(instructions.Where(x => instructions[findIndexIf].Label == x.Argument1 && x.Operation == "goto").ElementAt(0));

            wasChanged = true;
            if (instructions[findIndexIf + 1].Label == "")
            {
                instructions[findIndexGoto] = new Instruction("", instructions[findIndexIf].Operation, instructions[findIndexIf].Argument1, instructions[findIndexIf].Argument2, instructions[findIndexIf].Result);
                var tmp = ThreeAddressCodeTmp.GenTmpLabel();
                instructions[findIndexIf] = new Instruction(tmp, "noop", "", "", "");
                instructions.Insert(findIndexGoto + 1, new Instruction("", "goto", tmp, "", ""));
            }
            else
            {
                instructions[findIndexGoto] = new Instruction("", instructions[findIndexIf].Operation, instructions[findIndexIf].Argument1, instructions[findIndexIf].Argument2, instructions[findIndexIf].Result);
                var tmp = instructions[findIndexIf + 1].Label;
                instructions[findIndexIf] = new Instruction("", "noop", "", "", "");
                instructions.Insert(findIndexGoto + 1, new Instruction("", "goto", tmp, "", ""));
            }
            return(instructions);
        }
        // устранение переходов через переходы (пример из презентации 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);
        }
Пример #4
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));
        }