public void EmitMul(Type type, bool @checked)
 {
     if (@checked)
     {
         Emit(MulOvfInstruction.Create(type));
     }
     else
     {
         Emit(MulInstruction.Create(type));
     }
 }
Example #2
0
        // Replaces copy and multiplication loops with Mul (clear loop [-] will also be replaced with Clear)
        // [->++>>>+++++>++<+<<<<<] becomes Mul(1,2) Mul(4,5) Mul(5,2) Mul(6,1) Clear(0)
        public List <InstructionBase> OptimizeCopyMultiplyLoop(List <InstructionBase> instructions)
        {
            List <InstructionBase> optimized = new List <InstructionBase>();

            int i = 0;

            while (true)
            {
                int previousI = i;

                // Find next leaf loop (loop without inner loop)
                bool found = false;
                while (i < instructions.Count)
                {
                    if (instructions[i] is OpenInstruction)
                    {
                        found = true;
                        break;
                    }
                    i++;
                }
                if (!found)                                           // no Open found
                {
                    optimized.AddRange(instructions.Skip(previousI)); // copy remaining instructions
                    break;
                }
                int j = i + 1;
                found = false;
                while (j < instructions.Count)
                {
                    if (instructions[j] is CloseInstruction)
                    {
                        found = true;
                        break;
                    }
                    if (instructions[j] is OpenInstruction)
                    {
                        i = j;
                    }
                    j++;
                }
                if (!found)                                           // no leaf loop found
                {
                    optimized.AddRange(instructions.Skip(previousI)); // copy remaining instructions
                    break;
                }
                // copy instructions before loop
                optimized.AddRange(instructions.Skip(previousI).Take(i - previousI));
                // check it contains only Add, Sub, Left, Right
                List <InstructionBase> loopInstructions = instructions.Skip(i + 1).Take(j - i - 1).ToList();
                bool ok = loopInstructions.All(x => x is ArithmeticInstructionBase || x is PositionInstructionBase);
                if (!ok)
                {
                    optimized.AddRange(instructions.Skip(i).Take(j - i + 1)); // copy loop instructions
                    i = j + 1;
                    continue;                                                 // search another loop
                }
                // interpret loop and track pointer position and what arithmetic operations it carries out
                Dictionary <int, int> mem = new Dictionary <int, int>();
                int p = 0;
                foreach (InstructionBase instruction in loopInstructions) // contains only Add/Sub/Left/Right
                {
                    switch (instruction)
                    {
                    // Add
                    case AddInstruction add:
                        mem[p + add.Offset] = mem.Get(p + add.Offset, 0) + add.X;
                        break;

                    // Sub
                    case SubInstruction sub:
                        mem[p + sub.Offset] = mem.Get(p + sub.Offset, 0) - sub.X;
                        break;

                    // Left
                    case LeftInstruction left:
                        p -= left.X;
                        break;

                    // Right
                    case RightInstruction right:
                        p += right.X;
                        break;
                    }
                }
                // if pointed ended where it started and we subtracted exactly 1 from cell 0, then loop can be replaced with copy/mul instruction
                if (p != 0 || mem.Get(0, 0) != -1)                            // not a copy/mul instruction
                {
                    optimized.AddRange(instructions.Skip(i).Take(j - i + 1)); // copy loop instructions
                    i = j + 1;
                    continue;
                }
                mem.Remove(0);
                Debug.Write($"Replacing loop {string.Join(" ", loopInstructions.Select(x => x.ToIntermediateRepresentation()))} with ");
                // add Mul operations
                foreach (KeyValuePair <int, int> kv in mem)
                {
                    MulInstruction mulInstruction = new MulInstruction
                    {
                        Factor = (short)kv.Value,
                        Offset = kv.Key,
                    };
                    optimized.Add(mulInstruction);
                    Debug.Write($"{mulInstruction.ToIntermediateRepresentation()}, ");
                }
                // add Clear operation
                ClearInstruction clearInstruction = new ClearInstruction();
                optimized.Add(clearInstruction);
                Debug.WriteLine(clearInstruction.ToIntermediateRepresentation());
                //
                i = j + 1;
            }

            return(optimized);
        }
Example #3
0
 public void EmitMul(Type type, bool @checked)
 {
     Emit(@checked ? MulOvfInstruction.Create(type) : MulInstruction.Create(type));
 }
Example #4
0
        private bool GenerateNode(out OneOperandNode node)
        {
            node = null;

            InstructionToken instructionToken;

            if (this.ExpectInstructionToken(out instructionToken))
            {
                Instructions instruction = instructionToken.Instruction;
                switch (instruction)
                {
                case Instructions.Mov:
                {
                    Token operand1;
                    Token operand2;
                    if (this.ExpectTwoOperands(out operand1, out operand2))
                    {
                        node = new MovInstruction(this.rawInput, instructionToken, operand1, operand2);
                    }
                    else
                    {
                        this.LogExpectedTwoOperandsError(instructionToken);
                        return(false);
                    }
                }
                break;

                case Instructions.Add:
                {
                    Token operand1;
                    Token operand2;
                    if (this.ExpectTwoOperands(out operand1, out operand2))
                    {
                        node = new AddInstruction(this.rawInput, instructionToken, operand1, operand2);
                    }
                    else
                    {
                        this.LogExpectedTwoOperandsError(instructionToken);
                        return(false);
                    }
                }
                break;

                case Instructions.Sub:
                {
                    Token operand1;
                    Token operand2;
                    if (this.ExpectTwoOperands(out operand1, out operand2))
                    {
                        node = new SubInstruction(this.rawInput, instructionToken, operand1, operand2);
                    }
                    else
                    {
                        this.LogExpectedTwoOperandsError(instructionToken);
                        return(false);
                    }
                }
                break;

                case Instructions.Mul:
                {
                    Token operand1;
                    Token operand2;
                    if (this.ExpectTwoOperands(out operand1, out operand2))
                    {
                        node = new MulInstruction(this.rawInput, instructionToken, operand1, operand2);
                    }
                    else
                    {
                        this.LogExpectedTwoOperandsError(instructionToken);
                        return(false);
                    }
                }
                break;

                case Instructions.Div:
                {
                    Token operand1;
                    Token operand2;
                    if (this.ExpectTwoOperands(out operand1, out operand2))
                    {
                        node = new DivInstruction(this.rawInput, instructionToken, operand1, operand2);
                    }
                    else
                    {
                        this.LogExpectedTwoOperandsError(instructionToken);
                        return(false);
                    }
                }
                break;

                case Instructions.Cmp:
                {
                    Token operand1;
                    Token operand2;
                    if (this.ExpectTwoOperands(out operand1, out operand2))
                    {
                        node = new CmpInstruction(this.rawInput, instructionToken, operand1, operand2);
                    }
                    else
                    {
                        this.LogExpectedTwoOperandsError(instructionToken);
                        return(false);
                    }
                }
                break;

                case Instructions.Inc:
                {
                    Token operand;
                    if (this.ExpectOneOperand(out operand))
                    {
                        node = new IncInstruction(this.rawInput, instructionToken, operand);
                    }
                    else
                    {
                        this.LogExpectedOneOperandError(instructionToken);
                        return(false);
                    }
                }
                break;

                case Instructions.Dec:
                {
                    Token operand;
                    if (this.ExpectOneOperand(out operand))
                    {
                        node = new DecInstruction(this.rawInput, instructionToken, operand);
                    }
                    else
                    {
                        this.LogExpectedOneOperandError(instructionToken);
                        return(false);
                    }
                }
                break;

                case Instructions.Jmp:
                {
                    Token operand;
                    if (this.ExpectOneOperand(out operand))
                    {
                        node = new JmpInstruction(this.rawInput, instructionToken, operand);
                    }
                    else
                    {
                        this.LogExpectedOneOperandError(instructionToken);
                        return(false);
                    }
                }
                break;

                case Instructions.Jeq:
                {
                    Token operand;
                    if (this.ExpectOneOperand(out operand))
                    {
                        node = new JeqInstruction(this.rawInput, instructionToken, operand);
                    }
                    else
                    {
                        this.LogExpectedOneOperandError(instructionToken);
                        return(false);
                    }
                }
                break;

                case Instructions.Jne:
                {
                    Token operand;
                    if (this.ExpectOneOperand(out operand))
                    {
                        node = new JneInstruction(this.rawInput, instructionToken, operand);
                    }
                    else
                    {
                        this.LogExpectedOneOperandError(instructionToken);
                        return(false);
                    }
                }
                break;

                case Instructions.Jsm:
                {
                    Token operand;
                    if (this.ExpectOneOperand(out operand))
                    {
                        node = new JsmInstruction(this.rawInput, instructionToken, operand);
                    }
                    else
                    {
                        this.LogExpectedOneOperandError(instructionToken);
                        return(false);
                    }
                }
                break;

                case Instructions.Jns:
                {
                    Token operand;
                    if (this.ExpectOneOperand(out operand))
                    {
                        node = new JnsInstruction(this.rawInput, instructionToken, operand);
                    }
                    else
                    {
                        this.LogExpectedOneOperandError(instructionToken);
                        return(false);
                    }
                }
                break;
                }
            }

            return(true);
        }