Пример #1
0
 /// <summary>
 /// Performs stage specific processing on the compiler context.
 /// </summary>
 public virtual void Run()
 {
     for (int index = 0; index < BasicBlocks.Count; index++)
         for (Context ctx = new Context (InstructionSet, BasicBlocks[index]); !ctx.EndOfInstruction; ctx.GotoNext ())
             if (ctx.Instruction != null)
                 ctx.Clone ().Visit (this);
 }
Пример #2
0
        /// <summary>
        /// Performs stage specific processing on the compiler context.
        /// </summary>
        public void Run()
        {
            _numberOfMethods++;

            foreach (BasicBlock block in BasicBlocks)
            {
                for (Context ctx = CreateContext(block); !ctx.EndOfInstruction; ctx.GotoNext())
                {
                    Visit(ctx);
                }
            }
        }
        /// <summary>
        /// Assigns every instruction an increasing offset value.
        /// </summary>
        private void NumberInstructions()
        {
            int offset = 0;

            foreach (BasicBlock block in basicBlocks)
            {
                for (Context ctx = CreateContext(block); !ctx.EndOfInstruction; ctx.GotoNext())
                {
                    ctx.Offset = offset++;
                }
            }
        }
Пример #4
0
        /// <summary>
        /// Performs stage specific processing on the compiler context.
        /// </summary>
        public void Run()
        {
            // Prepare the registers used for the evaluation stack
            this.PrepareEvaluationStack(Architecture);

            foreach (BasicBlock block in BasicBlocks)
            {
                for (Context ctx = CreateContext(block); !ctx.EndOfInstruction; ctx.GotoNext())
                {
                    ProcessInstruction(ctx);
                }
            }
        }
Пример #5
0
        /// <summary>
        /// Builds the block links.
        /// </summary>
        /// <param name="block">The current block.</param>
        private void BuildBlockLinks(BasicBlock block)
        {
            for (Context ctx = CreateContext(block); !ctx.EndOfInstruction; ctx.GotoNext())
            {
                switch (ctx.Instruction.FlowControl)
                {
                case FlowControl.Next: continue;

                case FlowControl.Call: continue;

                case FlowControl.Return:
                    if (!block.NextBlocks.Contains(_epilogue))
                    {
                        LinkBlocks(block, _epilogue);
                    }
                    return;

                case FlowControl.Break: goto case FlowControl.Branch;

                case FlowControl.Throw: goto case FlowControl.Branch;

                case FlowControl.Switch: goto case FlowControl.ConditionalBranch;

                case FlowControl.Branch: {
                    BasicBlock next = FindBlock(ctx.Branch.Targets[0]);
                    if (!block.NextBlocks.Contains(next))
                    {
                        LinkBlocks(block, next);
                        BuildBlockLinks(next);
                    }
                    return;
                }

                case FlowControl.ConditionalBranch:
                    foreach (int target in ctx.Branch.Targets)
                    {
                        BasicBlock next = FindBlock(target);
                        if (!block.NextBlocks.Contains(next))
                        {
                            LinkBlocks(block, next);
                            BuildBlockLinks(next);
                        }
                    }
                    continue;

                default:
                    Debug.Assert(false);
                    break;
                }
            }
        }
        /// <summary>
        /// Performs stage specific processing on the compiler context.
        /// </summary>
        public void Run()
        {
            bool remove = false;

            foreach (BasicBlock block in basicBlocks)
            {
                for (Context ctx = new Context(InstructionSet, block); !ctx.EndOfInstruction; ctx.GotoNext())
                {
                    if (ctx.Instruction is IR.MoveInstruction || ctx.Instruction is CIL.StlocInstruction)
                    {
                        if (ctx.Operand1 is ConstantOperand)
                        {
                            // HACK: We can't track a constant through a register, so we keep those moves
                            if (ctx.Result is StackOperand)
                            {
                                Debug.Assert(ctx.Result.Definitions.Count == 1, @"Operand defined multiple times. Instruction stream not in SSA form!");
                                ctx.Result.Replace(ctx.Operand1, InstructionSet);
                                remove = true;
                            }
                        }
                    }
                    else if (ctx.Instruction is IR.PhiInstruction)
                    {
                        IR.PhiInstruction phi = (IR.PhiInstruction)ctx.Instruction;
                        ConstantOperand co = ctx.Operand2 as ConstantOperand;
                        List<BasicBlock> blocks = ctx.Other as List<BasicBlock>;	// FIXME PG / ctx has moved
                        if (co != null && blocks.Count == 1)
                        {
                            // We can remove the phi, as it is only defined once
                            // HACK: We can't track a constant through a register, so we keep those moves
                            if (!ctx.Result.IsRegister)
                            {
                                Debug.Assert(ctx.Result.Definitions.Count == 1, @"Operand defined multiple times. Instruction stream not in SSA form!");
                                ctx.Result.Replace(co, InstructionSet);
                                remove = true;
                            }
                        }
                    }

                    // Shall we remove this instruction?
                    if (remove)
                    {
                        ctx.Remove();
                        remove = false;
                    }

                }
            }
        }
Пример #7
0
        /// <summary>
        /// Builds the block links.
        /// </summary>
        /// <param name="block">The current block.</param>
        private void BuildBlockLinks(BasicBlock block)
        {
            for (Context ctx = CreateContext(block); !ctx.EndOfInstruction; ctx.GotoNext())
            {
                switch (ctx.Instruction.FlowControl)
                {
                case FlowControl.Next: continue;

                case FlowControl.Call: continue;

                case FlowControl.Return:
                    if (!block.NextBlocks.Contains(_epilogue))
                    {
                        LinkBlocks(block, _epilogue);
                    }
                    return;

                case FlowControl.Break: goto case FlowControl.Branch;

                // FIXME: case FlowControl.Throw: goto case FlowControl.Branch;
                case FlowControl.Switch: goto case FlowControl.ConditionalBranch;

                case FlowControl.Branch:
                {
                    FindAndLinkBlock(block, ctx.Branch.Targets[0]);
                    return;
                }

                case FlowControl.ConditionalBranch:
                    foreach (int target in ctx.Branch.Targets)
                    {
                        FindAndLinkBlock(block, target);
                    }

                    // Conditional blocks are at least two way branches. The old way of adding jumps didn't properly
                    // resolve operands under certain circumstances. This does.
                    int nextIndex = ctx.Index + 1;
                    if (nextIndex < this.InstructionSet.Used)
                    {
                        FindAndLinkBlock(block, this.InstructionSet.Data[nextIndex].Label);
                    }
                    continue;

                default:
                    Debug.Assert(false);
                    break;
                }
            }
        }
        /// <summary>
        /// Performs stage specific processing on the compiler context.
        /// </summary>
        public void Run()
        {
            _registerSet = Architecture.RegisterSet;
            _activeOperands = new Operand[_registerSet.Length];
            Debug.Assert(0 != _activeOperands.Length, @"No registers in the architecture?");
            _activeOpLastUse = new Context[_registerSet.Length];

            // Iterate basic Blocks
            foreach (BasicBlock block in BasicBlocks) {

                // Iterate all instructions in the block
                // Assign registers to all operands, where this needs to be done
                for (Context ctx = new Context(InstructionSet, block); !ctx.EndOfInstruction; ctx.GotoNext())
                    AssignRegisters(ctx);

                // Spill active registers at the end of a block (they're reloaded in the next, if necessary.)
                SpillActiveOperands(block);
            }
        }
        /// <summary>
        /// Logs the instructions in the given enumerable to the trace.
        /// </summary>
        /// <param name="ctx">The context.</param>
        private void LogInstructions(Context ctx)
        {
            StringBuilder text = new StringBuilder();

            for (; !ctx.EndOfInstruction; ctx.GotoNext()) {

                text.Length = 0;

                if (ctx.Instruction == null)
                    continue;

                if (ctx.Ignore)
                    text.Append("; ");

                text.AppendFormat("L_{0:X4}: {1}", ctx.Label, ctx.Instruction.ToString(ctx));

                Debug.WriteLine(text.ToString());
            }
        }
Пример #10
0
        /// <summary>
        /// Logs the instructions in the given enumerable to the trace.
        /// </summary>
        /// <param name="ctx">The context.</param>
        private void LogInstructions(Context ctx)
        {
            StringBuilder text = new StringBuilder();

            for (; !ctx.EndOfInstruction; ctx.GotoNext())
            {
                text.Length = 0;

                if (ctx.Instruction == null)
                {
                    continue;
                }

                if (ctx.Ignore)
                {
                    text.Append("; ");
                }

                text.AppendFormat("L_{0:X4}: {1}", ctx.Label, ctx.Instruction.ToString(ctx));

                Debug.WriteLine(text.ToString());
            }
        }
        /// <summary>
        /// Enumerates all instructions and eliminates floating point constants from them.
        /// </summary>
        /// <param name="ctx">The context.</param>
        /// <param name="ctxEpilogue">The context of the epilogue.</param>
        private void ProcessInstructions(Context ctx, Context ctxEpilogue)
        {
            // Current constant operand
            ConstantOperand co = null;

            for (; !ctx.EndOfInstruction; ctx.GotoNext())
            {
                // A constant may only appear on the right side of an expression, so we ignore constants in
                // result - there should never be one there.
                foreach (Operand op in ctx.Operands)
                {
                    co = op as ConstantOperand;
                    if (co != null && IsLargeConstant(co))
                    {
                        // Move the constant out of the code stream and place it right after the code.
                        ctxEpilogue.AppendInstruction(CPUx86.Instruction.LiteralInstruction);
                        ctxEpilogue.LiteralData = new IR.LiteralData(ctx.Label, co.Type, co.Value);

                        op.Replace(((ctxEpilogue.Instruction) as CPUx86.LiteralInstruction).CreateOperand(ctxEpilogue), InstructionSet);

                        _constantRemoved = true;
                    }

                }
            }
        }
 /// <summary>
 /// Performs stage specific processing on the compiler context.
 /// </summary>
 public virtual void Run()
 {
     for (int index = 0; index < basicBlocks.Count; index++)
     {
         for (Context ctx = new Context(InstructionSet, basicBlocks[index]); !ctx.EndOfInstruction; ctx.GotoNext())
         {
             if (ctx.Instruction != null)
             {
                 ctx.Clone().Visit(this);
             }
         }
     }
 }
Пример #13
0
        /// <summary>
        /// Processes the instructions.
        /// </summary>
        /// <param name="block">The block.</param>
        /// <param name="currentStack">The current stack.</param>
        /// <param name="compiler">The compiler.</param>
        private void ProcessInstructions(BasicBlock block, IList<Operand> currentStack, IMethodCompiler compiler)
        {
            for (Context ctx = new Context (InstructionSet, block); !ctx.EndOfInstruction; ctx.GotoNext ())
            {
                if (!(ctx.Instruction is CIL.ICILInstruction))
                    continue;

                AssignOperandsFromCILStack (ctx, currentStack);

                (ctx.Instruction as ICILInstruction).Validate (ctx, compiler);

                PushResultOperands (ctx, currentStack);
            }
        }
Пример #14
0
 /// <summary>
 /// Collects all local variables assignments into a list.
 /// </summary>
 /// <param name="locals">Holds all locals found by the stage.</param>
 /// <param name="block">The block.</param>
 private void CollectLocalVariables(List<StackOperand> locals, BasicBlock block)
 {
     for (Context ctx = new Context(InstructionSet, block); !ctx.EndOfInstruction; ctx.GotoNext())
     {
         // Does this instruction define a new stack variable?
         foreach (Operand op in ctx.Results)
         {
             // The instruction list may not be in SSA form, so we have to check existence again here unfortunately.
             // FIXME: Allow us to detect the state of blocks
             LocalVariableOperand lvop = op as LocalVariableOperand;
             if (lvop != null && !locals.Contains(lvop))
                 locals.Add(lvop);
         }
     }
 }
Пример #15
0
 /// <summary>
 /// Collects all local variables assignments into a list.
 /// </summary>
 /// <param name="locals">Holds all locals found by the stage.</param>
 /// <param name="block">The block.</param>
 private void CollectLocalVariables(List <StackOperand> locals, BasicBlock block)
 {
     for (Context ctx = new Context(InstructionSet, block); !ctx.EndOfInstruction; ctx.GotoNext())
     {
         // Does this instruction define a new stack variable?
         foreach (Operand op in ctx.Results)
         {
             // The instruction list may not be in SSA form, so we have to check existence again here unfortunately.
             // FIXME: Allow us to detect the state of blocks
             LocalVariableOperand lvop = op as LocalVariableOperand;
             if (lvop != null && !locals.Contains(lvop))
             {
                 locals.Add(lvop);
             }
         }
     }
 }
Пример #16
0
        /// <summary>
        /// Processes the instructions.
        /// </summary>
        /// <param name="block">The block.</param>
        /// <param name="currentStack">The current stack.</param>
        /// <param name="compiler">The compiler.</param>
        private void ProcessInstructions(BasicBlock block, IList <Operand> currentStack, IMethodCompiler compiler)
        {
            for (Context ctx = new Context(InstructionSet, block); !ctx.EndOfInstruction; ctx.GotoNext())
            {
                if (!(ctx.Instruction is CIL.ICILInstruction))
                {
                    continue;
                }

                AssignOperandsFromCILStack(ctx, currentStack);

                (ctx.Instruction as ICILInstruction).Validate(ctx, compiler);

                PushResultOperands(ctx, currentStack);
            }
        }
        /// <summary>
        /// Assigns the operands.
        /// </summary>
        /// <param name="block">The block.</param>
        private void AssignOperands(BasicBlock block)
        {
            if (block.InitialStack != null)
                foreach (Operand operand in block.InitialStack)
                    _operandStack.Push(operand);

            for (Context ctx = new Context(InstructionSet, block); !ctx.EndOfInstruction; ctx.GotoNext())
            {
                if (!(ctx.Instruction is IBranchInstruction) && !(ctx.Instruction is ICILInstruction))
                    continue;

                if (!(ctx.Instruction is IR.JmpInstruction))
                {
                    AssignOperandsFromCILStack(ctx, _operandStack);
                    (ctx.Instruction as ICILInstruction).Validate(ctx, MethodCompiler);
                    PushResultOperands(ctx, _operandStack);
                }

                if (ctx.Instruction is IBranchInstruction)
                {
                    Stack<Operand> initialStack = GetCurrentStack(_operandStack);
                    CreateTemporaryMoves(ctx, block, initialStack);
                    break;
                }
            }

            MarkAsProcessed(block);

            foreach (BasicBlock b in block.NextBlocks)
            {
                if (IsNotProcessed(b))
                    AssignOperands(b);
            }
        }
Пример #18
0
        /// <summary>
        /// Performs stage specific processing on the compiler context.
        /// </summary>
        public void Run()
        {
            _registerSet    = architecture.RegisterSet;
            _activeOperands = new Operand[_registerSet.Length];
            Debug.Assert(0 != _activeOperands.Length, @"No registers in the architecture?");
            _activeOpLastUse = new Context[_registerSet.Length];

            // Iterate basic Blocks
            foreach (BasicBlock block in basicBlocks)
            {
                // Iterate all instructions in the block
                // Assign registers to all operands, where this needs to be done
                for (Context ctx = new Context(InstructionSet, block); !ctx.EndOfInstruction; ctx.GotoNext())
                {
                    AssignRegisters(ctx);
                }

                // Spill active registers at the end of a block (they're reloaded in the next, if necessary.)
                SpillActiveOperands(block);
            }
        }
Пример #19
0
        private bool TransformToSsaForm(Context ctx, BasicBlock caller, IDictionary <StackOperand, StackOperand> liveIn, out IDictionary <StackOperand, StackOperand> liveOut)
        {
            // Is this another entry for this block?
            IDictionary <StackOperand, StackOperand> liveOutPrev = _liveness[ctx.BasicBlock.Sequence];

            if (liveOutPrev != null)
            {
                // FIXME: Merge PHIs with new incoming variables, add new incoming variables to out set
                // and schedule the remaining out nodes/quit
                MergePhiInstructions(ctx.BasicBlock, caller, liveIn);
                liveOut = liveOutPrev;

                return(false);
            }
            // Is this a dominance frontier block?
            if (Array.IndexOf(_dominanceFrontierBlocks, ctx.BasicBlock) != -1)
            {
                InsertPhiInstructions(ctx, caller, liveIn);
            }

            // Create a new live out dictionary
            if (liveIn != null)
            {
                liveOut = new Dictionary <StackOperand, StackOperand> (liveIn, s_comparer);
            }
            else
            {
                liveOut = new Dictionary <StackOperand, StackOperand> (s_comparer);
            }

            // Iterate each instruction in the block
            for (Context ctxBlock = CreateContext(ctx.BasicBlock); !ctxBlock.EndOfInstruction; ctxBlock.GotoNext())
            {
                // Replace all operands with their current SSA version
                UpdateUses(ctxBlock, liveOut);

                // Is this an instruction we ignore?
                if (!ctx.Ignore)
                {
                    RenameStackOperands(ctxBlock, liveOut);
                }
            }

            return(true);
        }
        private IEnumerable<Context> ScanForOperatorNew()
        {
            foreach (BasicBlock block in this.BasicBlocks)
            {
                Context context = new Context(InstructionSet, block);
                while (context.EndOfInstruction == false)
                {
                    if (context.Instruction is NewobjInstruction || context.Instruction is NewarrInstruction)
                    {
                        Debug.WriteLine(@"StaticAllocationResolutionStage: Found a newobj or newarr instruction.");
                        yield return context.Clone();
                    }

                    context.GotoNext();
                }
            }
        }
Пример #21
0
        /// <summary>
        /// Called to emit a list of instructions offered by the instruction provider.
        /// </summary>
        protected virtual void EmitInstructions()
        {
            //ExceptionClauseHeader exceptionClauseHeader = this.methodCompiler.Method.ExceptionClauseHeader;
            foreach (BasicBlock block in basicBlocks)
            {
                BlockStart(block);

                for (Context ctx = new Context(InstructionSet, block); !ctx.EndOfInstruction; ctx.GotoNext())
                {
                    if (ctx.Instruction != null)
                    {
                        if (!ctx.Ignore)
                        {
                            if (block.ExceptionHeaderClause != null)
                            {
                                block.ExceptionHeaderClause.Update(ctx, codeStream);
                                block.ExceptionHeaderClause.AddLabelToCodeStream(codeEmitter);
                            }
                            IPlatformInstruction instruction = ctx.Instruction as IPlatformInstruction;
                            if (instruction != null)
                            {
                                instruction.Emit(ctx, codeEmitter);
                            }
                            else
                            {
                                Debug.WriteLine("Missing Code Transformation: " + ctx.ToString());
                            }
                        }
                    }
                }

                BlockEnd(block);
            }
        }
Пример #22
0
        /// <summary>
        /// Assigns the operands.
        /// </summary>
        /// <param name="block">The block.</param>
        private void AssignOperands(BasicBlock block)
        {
            //Debug.WriteLine(@"OperandDeterminationStage: Assigning operands to block " + block);
            if (block.InitialStack != null)
            {
                foreach (Operand operand in block.InitialStack)
                {
                    _operandStack.Push(operand);
                }
            }

            for (Context ctx = new Context(InstructionSet, block); !ctx.EndOfInstruction; ctx.GotoNext())
            {
                if (!(ctx.Instruction is IBranchInstruction) && !(ctx.Instruction is ICILInstruction))
                {
                    continue;
                }

                if (!(ctx.Instruction is IR.JmpInstruction))
                {
                    AssignOperandsFromCILStack(ctx, _operandStack);
                    (ctx.Instruction as ICILInstruction).Validate(ctx, methodCompiler);
                    PushResultOperands(ctx, _operandStack);
                }

                if (ctx.Instruction is IBranchInstruction)
                {
                    Stack <Operand> initialStack = GetCurrentStack(_operandStack);
                    CreateTemporaryMoves(ctx, block, initialStack);
                    break;
                }
            }

            MarkAsProcessed(block);

            foreach (BasicBlock b in block.NextBlocks)
            {
                if (IsNotProcessed(b))
                {
                    AssignOperands(b);
                }
            }
        }
Пример #23
0
        /// <summary>
        /// Finds all targets.
        /// </summary>
        /// <param name="index">The index.</param>
        private void SplitIntoBlocks(int index)
        {
            Dictionary <int, int> targets = new Dictionary <int, int>();

            targets.Add(index, -1);

            // Find out all targets labels
            for (Context ctx = new Context(InstructionSet, index); !ctx.EndOfInstruction; ctx.GotoNext())
            {
                switch (ctx.Instruction.FlowControl)
                {
                case FlowControl.Next: continue;

                case FlowControl.Call: continue;

                case FlowControl.Break:
                    goto case FlowControl.Branch;

                case FlowControl.Return:
                    continue;

                case FlowControl.Throw:
                    goto case FlowControl.Branch;

                case FlowControl.Branch:
                    // Unconditional branch
                    Debug.Assert(ctx.Branch.Targets.Length == 1);
                    if (!targets.ContainsKey(ctx.Branch.Targets[0]))
                    {
                        targets.Add(ctx.Branch.Targets[0], -1);
                    }
                    continue;

                case FlowControl.Switch: goto case FlowControl.ConditionalBranch;

                case FlowControl.ConditionalBranch:
                    // Conditional branch with multiple targets
                    foreach (int target in ctx.Branch.Targets)
                    {
                        if (!targets.ContainsKey(target))
                        {
                            targets.Add(target, -1);
                        }
                    }
                    int next = ctx.Next.Label;
                    if (!targets.ContainsKey(next))
                    {
                        targets.Add(next, -1);
                    }
                    continue;

                default:
                    Debug.Assert(false);
                    break;
                }
            }

            bool slice = false;

            for (Context ctx = new Context(InstructionSet, index); !ctx.EndOfInstruction; ctx.GotoNext())
            {
                FlowControl flow;

                if (targets.ContainsKey(ctx.Label))
                {
                    CreateBlock(ctx.Label, ctx.Index);

                    if (!ctx.IsFirstInstruction)
                    {
                        Context prev = ctx.Previous;
                        flow = prev.Instruction.FlowControl;
                        if (flow == FlowControl.Next || flow == FlowControl.Call || flow == FlowControl.ConditionalBranch || flow == FlowControl.Switch)
                        {
                            prev.AppendInstruction(IR.Instruction.JmpInstruction);
                            prev.SetBranch(ctx.Label);
                            prev.SliceAfter();
                        }
                    }

                    targets.Remove(ctx.Label);
                }

                if (slice)
                {
                    ctx.SliceBefore();
                }

                flow = ctx.Instruction.FlowControl;

                slice = (flow == FlowControl.Return || flow == FlowControl.Branch || flow == FlowControl.ConditionalBranch || flow == FlowControl.Break || flow == FlowControl.Throw);
            }

            Debug.Assert(targets.Count <= 1);

            if (FindBlock(0) == null)
            {
                CreateBlock(0, index);
            }
        }
Пример #24
0
        /// <summary>
        /// Called to emit a list of instructions offered by the instruction provider.
        /// </summary>
        protected virtual void EmitInstructions()
        {
            foreach (BasicBlock block in BasicBlocks)
            {
                BlockStart(block);

                for (Context ctx = new Context(InstructionSet, block); !ctx.EndOfInstruction; ctx.GotoNext())
                {
                    if (ctx.Instruction != null)
                    {
                        if (!ctx.Ignore)
                        {
                            IPlatformInstruction instruction = ctx.Instruction as IPlatformInstruction;
                            if (instruction != null)
                            {
                                instruction.Emit(ctx, _codeEmitter);
                            }
                            else
                            {
                                Debug.WriteLine("Missing Code Transformation: " + ctx.ToString());
                            }
                        }
                    }
                }

                BlockEnd(block);
            }
        }
Пример #25
0
        /// <summary>
        /// Eliminates the common subexpressions.
        /// </summary>
        /// <param name="ctx">The context.</param>
        private static void EliminateCommonSubexpressions(Context ctx)
        {
            List <AEBinExp> AEB = new List <AEBinExp> ();
            List <AEBinExp> tmp;

            AEBinExp aeb;

            for (; !ctx.EndOfInstruction; ctx.GotoNext())
            {
                IInstruction instruction = ctx.Instruction;
                // block.Instructions[i];
                RegisterOperand temp  = null;
                bool            found = false;

                if ((instruction is CIL.ArithmeticInstruction) && (instruction is CIL.BinaryInstruction))
                {
                    tmp = new List <AEBinExp> (AEB);

                    while (tmp.Count > 0)
                    {
                        aeb = tmp[0];
                        tmp.RemoveAt(0);

                        // Match current instruction's expression against those
                        // in AEB, including commutativity
                        if (IsCommutative(instruction))
                        {
                            //int position = aeb.Position;
                            found = true;

                            // If no variable in tuple, create a new temporary and
                            // insert an instruction evaluating the expression
                            // and assigning it to the temporary
                            if (aeb.Var == null)
                            {
                                // new_tmp()
                                AEB.Remove(aeb);
                                AEB.Add(new AEBinExp(aeb.Position, aeb.Operand1, aeb.Operator, aeb.Operand2, temp));

                                // Insert new assignment to instruction stream in block
                                Context inserted = ctx.InsertBefore();

                                switch (aeb.Operator)
                                {
                                case Operation.Add:
                                    inserted.SetInstruction(CIL.Instruction.Get(CIL.OpCode.Add), temp, aeb.Operand1, aeb.Operand2);
                                    break;

                                case Operation.Mul:
                                    inserted.SetInstruction(CIL.Instruction.Get(CIL.OpCode.Mul), temp, aeb.Operand1, aeb.Operand2);
                                    break;

                                case Operation.Or:
                                    inserted.SetInstruction(CIL.Instruction.Get(CIL.OpCode.Or), temp, aeb.Operand1, aeb.Operand2);
                                    break;

                                case Operation.Xor:
                                    inserted.SetInstruction(CIL.Instruction.Get(CIL.OpCode.Xor), temp, aeb.Operand1, aeb.Operand2);
                                    break;

                                default:
                                    break;
                                }

                                //block.Instructions.Insert(position, inst);

                                //++position;
                                //++i;

                                // Replace current instruction by one that copies
                                // the temporary instruction
                                // FIXME PG:
                                // block.Instructions[position] = new IR.MoveInstruction(block.Instructions[position].Results[0], temp);
                                // ctx.SetInstruction(IR.MoveInstruction); // FIXME PG
                                // ctx.Result = block.Instructions[position].Results[0]; // FIXME PG
                                ctx.Operand1 = temp;
                            }
                            else
                            {
                                temp = (RegisterOperand)aeb.Var;
                            }

                            // FIXME PG
                            // block.Instructions[i] = new IR.MoveInstruction(instruction.Results[0], temp);
                        }
                    }

                    if (!found)
                    {
                        Operation opr = Operation.None;

                        if (instruction is CIL.AddInstruction)
                        {
                            opr = Operation.Add;
                        }
                        else if (instruction is CIL.MulInstruction)
                        {
                            opr = Operation.Mul;
                        }
                        else if (instruction is IR.LogicalAndInstruction)
                        {
                            opr = Operation.And;
                        }
                        // Insert new tuple
                        AEB.Add(new AEBinExp(ctx.Index, ctx.Operand1, opr, ctx.Operand2, null));
                    }

                    // Remove all tuples that use the variable assigned to by
                    // the current instruction
                    tmp = new List <AEBinExp> (AEB);

                    while (tmp.Count > 0)
                    {
                        aeb = tmp[0];
                        tmp.RemoveAt(0);

                        if (ctx.Operand1 == aeb.Operand1 || ctx.Operand2 == aeb.Operand2)
                        {
                            AEB.Remove(aeb);
                        }
                    }
                }
            }
        }
Пример #26
0
        /// <summary>
        /// Eliminates the common subexpressions.
        /// </summary>
        /// <param name="ctx">The context.</param>
        private static void EliminateCommonSubexpressions(Context ctx)
        {
            List<AEBinExp> AEB = new List<AEBinExp>();
            List<AEBinExp> tmp;

            AEBinExp aeb;

            for (; !ctx.EndOfInstruction; ctx.GotoNext()) {
                IInstruction instruction = ctx.Instruction; // block.Instructions[i];
                RegisterOperand temp = null;
                bool found = false;

                if ((instruction is CIL.ArithmeticInstruction) && (instruction is CIL.BinaryInstruction)) {
                    tmp = new List<AEBinExp>(AEB);

                    while (tmp.Count > 0) {
                        aeb = tmp[0];
                        tmp.RemoveAt(0);

                        // Match current instruction's expression against those
                        // in AEB, including commutativity
                        if (IsCommutative(instruction)) {
                            //int position = aeb.Position;
                            found = true;

                            // If no variable in tuple, create a new temporary and
                            // insert an instruction evaluating the expression
                            // and assigning it to the temporary
                            if (aeb.Var == null) {
                                // new_tmp()
                                AEB.Remove(aeb);
                                AEB.Add(new AEBinExp(aeb.Position, aeb.Operand1, aeb.Operator, aeb.Operand2, temp));

                                // Insert new assignment to instruction stream in block
                                Context inserted = ctx.InsertBefore();

                                switch (aeb.Operator) {
                                    case Operation.Add:
                                        inserted.SetInstruction(CIL.Instruction.Get(CIL.OpCode.Add), temp, aeb.Operand1, aeb.Operand2);
                                        break;
                                    case Operation.Mul:
                                        inserted.SetInstruction(CIL.Instruction.Get(CIL.OpCode.Mul), temp, aeb.Operand1, aeb.Operand2);
                                        break;
                                    case Operation.Or:
                                        inserted.SetInstruction(CIL.Instruction.Get(CIL.OpCode.Or), temp, aeb.Operand1, aeb.Operand2);
                                        break;
                                    case Operation.Xor:
                                        inserted.SetInstruction(CIL.Instruction.Get(CIL.OpCode.Xor), temp, aeb.Operand1, aeb.Operand2);
                                        break;
                                    default:
                                        break;
                                }

                                //block.Instructions.Insert(position, inst);

                                //++position;
                                //++i;

                                // Replace current instruction by one that copies
                                // the temporary instruction
                                // FIXME PG:
                                // block.Instructions[position] = new IR.MoveInstruction(block.Instructions[position].Results[0], temp);
                                // ctx.SetInstruction(IR.MoveInstruction); // FIXME PG
                                // ctx.Result = block.Instructions[position].Results[0]; // FIXME PG
                                ctx.Operand1 = temp;
                            }
                            else {
                                temp = (RegisterOperand)aeb.Var;
                            }

                            // FIXME PG
                            // block.Instructions[i] = new IR.MoveInstruction(instruction.Results[0], temp);
                        }
                    }

                    if (!found) {
                        Operation opr = Operation.None;

                        if (instruction is CIL.AddInstruction)
                            opr = Operation.Add;
                        else if (instruction is CIL.MulInstruction)
                            opr = Operation.Mul;
                        else if (instruction is IR.LogicalAndInstruction)
                            opr = Operation.And;
                        // Insert new tuple
                        AEB.Add(new AEBinExp(ctx.Index, ctx.Operand1, opr, ctx.Operand2, null));
                    }

                    // Remove all tuples that use the variable assigned to by
                    // the current instruction
                    tmp = new List<AEBinExp>(AEB);

                    while (tmp.Count > 0) {
                        aeb = tmp[0];
                        tmp.RemoveAt(0);

                        if (ctx.Operand1 == aeb.Operand1 || ctx.Operand2 == aeb.Operand2)
                            AEB.Remove(aeb);
                    }
                }
            }
        }
Пример #27
0
        private void MergePhiInstructions(BasicBlock block, BasicBlock caller, IDictionary <StackOperand, StackOperand> liveIn)
        {
            for (Context ctx = new Context(InstructionSet, block); !ctx.EndOfInstruction; ctx.GotoNext())
            {
                IR.PhiInstruction phi = ctx.Instruction as IR.PhiInstruction;

                if (phi != null && liveIn.ContainsKey(ctx.Result as StackOperand))
                {
                    StackOperand value = liveIn[ctx.Result as StackOperand];

                    if (!IR.PhiInstruction.Contains(ctx, value) && (ctx.Result as StackOperand).Version != value.Version)
                    {
                        IR.PhiInstruction.AddValue(ctx, caller, value);
                    }
                }
            }
        }
        /// <summary>
        /// Runs the specified compiler.
        /// </summary>
        public void Run()
        {
            if (!methodCount.ContainsKey(MethodCompiler.Method.Name))
                methodCount[MethodCompiler.Method.Name] = 0;

            ++methodCount[MethodCompiler.Method.Name];

            // Retreive the first block
            firstBlock = FindBlock(-1);

            workList = new Stack<BasicBlock>();
            workList.Push(firstBlock);
            workArray = new BitArray(BasicBlocks.Count);

            string methodName = MethodCompiler.Method.Name;
            methodName = methodName.Replace("<", "");
            methodName = methodName.Replace(">", "");
            methodName = methodName.Replace("$", "");
            methodName = methodName.Replace(".", "");
            IPipelineStage previousStage = MethodCompiler.GetPreviousStage(typeof(IMethodCompilerStage));
            dotFile.WriteLine("subgraph cluster" + methodName + "_FlowGraph {");
            dotFile.WriteLine("label = \"Method: " + methodName + "(" + MethodCompiler.Method.Signature + ") after " + previousStage.Name + "\"");
            //dotFile.WriteLine("graph [rankdir = \"TB\"];");

            string nodes = string.Empty;
            string edges = string.Empty;

            foreach (BasicBlock block in BasicBlocks)
            {
                string nodeName = string.Empty;
                string nodeContent = string.Empty;
                string nextNode = string.Empty;

                nodeName = methodName + "_" + block.ToString();
                //nodeName = nodeName.Replace("-", "_");

                nodeContent += "<tr><td bgcolor=\"black\" align=\"center\" colspan=\"4\"><font face=\"Courier\" color=\"white\">L_" + block.Label.ToString("x4") + "</font></td></tr>";

                int field = 0;
                int i = 0;

                for (Context ctx = new Context(InstructionSet, block); !ctx.EndOfInstruction; ctx.GotoNext())
                {
                    if (ctx.Instruction == null)
                        continue;

                    string color;
                    string inst = ctx.Instruction.ToString(ctx).Replace("&", "&amp;");
                    inst = inst.Replace("<", "&lt;");
                    inst = inst.Replace(">", "&gt;");

                    if (inst.StartsWith("IL") || inst.StartsWith("T_"))
                        color = "#0000ff5f";
                    else if (inst.StartsWith("IR"))
                        color = "#ff00005f";
                    else
                        color = "#CFD6CEff";

                    nodeContent += "<tr height=\"20\"><td bgcolor=\"white\" align=\"right\" width=\"20\"><img src=\"icon.png\"/></td><td bgcolor=\"white\" align=\"right\">" + (i++) + "</td><td bgcolor=\"" + color + "\" align=\"center\" colspan=\"2\"><font face=\"Courier\">" + inst + "</font></td></tr>";

                    ++field;
                }

                if (nodeContent != string.Empty && nodeContent[nodeContent.Length - 1] == '|')
                    nodeContent = nodeContent.Substring(0, nodeContent.Length - 2);

                if (nodeContent != string.Empty)
                    nodes += "\"" + nodeName + "\" [label = <<table border=\"1\" cellborder=\"0\" cellpadding=\"3\" bgcolor=\"white\">" + nodeContent + "</table>> shape = \"Mrecord\"];\r\n";

                foreach (BasicBlock nextBlock in block.NextBlocks)
                {
                    nextNode = methodName + "_" + nextBlock.ToString();

                    edges += "\"" + nodeName + "\"" + " -> " + "\"" + nextNode + "\";\r\n";
                }
            }

            dotFile.WriteLine(nodes);
            dotFile.WriteLine(edges);
            dotFile.WriteLine("};");
        }
Пример #29
0
        /// <summary>
        /// Performs stage specific processing on the compiler context.
        /// </summary>
        public void Run()
        {
            bool remove = false;

            foreach (BasicBlock block in BasicBlocks)
            {
                for (Context ctx = new Context(InstructionSet, block); !ctx.EndOfInstruction; ctx.GotoNext())
                {
                    if (ctx.Instruction is IR.MoveInstruction || ctx.Instruction is CIL.StlocInstruction)
                    {
                        if (ctx.Operand1 is ConstantOperand)
                        {
                            // HACK: We can't track a constant through a register, so we keep those moves
                            if (ctx.Result is StackOperand)
                            {
                                Debug.Assert(ctx.Result.Definitions.Count == 1, @"Operand defined multiple times. Instruction stream not in SSA form!");
                                ctx.Result.Replace(ctx.Operand1, InstructionSet);
                                remove = true;
                            }
                        }
                    }
                    else if (ctx.Instruction is IR.PhiInstruction)
                    {
                        IR.PhiInstruction phi    = (IR.PhiInstruction)ctx.Instruction;
                        ConstantOperand   co     = ctx.Operand2 as ConstantOperand;
                        List <BasicBlock> blocks = ctx.Other as List <BasicBlock>;                              // FIXME PG / ctx has moved
                        if (co != null && blocks.Count == 1)
                        {
                            // We can remove the phi, as it is only defined once
                            // HACK: We can't track a constant through a register, so we keep those moves
                            if (!ctx.Result.IsRegister)
                            {
                                Debug.Assert(ctx.Result.Definitions.Count == 1, @"Operand defined multiple times. Instruction stream not in SSA form!");
                                ctx.Result.Replace(co, InstructionSet);
                                remove = true;
                            }
                        }
                    }

                    // Shall we remove this instruction?
                    if (remove)
                    {
                        ctx.Remove();
                        remove = false;
                    }
                }
            }
        }
        /// <summary>
        /// Called to emit a list of instructions offered by the instruction provider.
        /// </summary>
        protected virtual void EmitInstructions()
        {
            foreach (BasicBlock block in BasicBlocks) {
                BlockStart(block);

                for (Context ctx = new Context(InstructionSet, block); !ctx.EndOfInstruction; ctx.GotoNext())
                    if (ctx.Instruction != null)
                        if (!ctx.Ignore) {
                            IPlatformInstruction instruction = ctx.Instruction as IPlatformInstruction;
                            if (instruction != null)
                                instruction.Emit(ctx, _codeEmitter);
                            else
                                Debug.WriteLine("Missing Code Transformation: " + ctx.ToString());
                        }

                BlockEnd(block);
            }
        }
Пример #31
0
        /// <summary>
        /// Runs the specified compiler.
        /// </summary>
        public void Run()
        {
            if (!methodCount.ContainsKey(methodCompiler.Method.Name))
            {
                methodCount[methodCompiler.Method.Name] = 0;
            }

            ++methodCount[methodCompiler.Method.Name];

            // Retreive the first block
            firstBlock = FindBlock(-1);

            workList = new Stack <BasicBlock>();
            workList.Push(firstBlock);
            workArray = new BitArray(basicBlocks.Count);

            string methodName = methodCompiler.Method.Name;

            methodName = methodName.Replace("<", "");
            methodName = methodName.Replace(">", "");
            methodName = methodName.Replace("$", "");
            methodName = methodName.Replace(".", "");
            IPipelineStage previousStage = methodCompiler.GetPreviousStage(typeof(IMethodCompilerStage));

            dotFile.WriteLine("subgraph cluster" + methodName + "_FlowGraph {");
            dotFile.WriteLine("label = \"Method: " + methodName + "(" + methodCompiler.Method.Signature + ") after " + previousStage.Name + "\"");
            //dotFile.WriteLine("graph [rankdir = \"TB\"];");

            string nodes = string.Empty;
            string edges = string.Empty;

            foreach (BasicBlock block in basicBlocks)
            {
                string nodeName    = string.Empty;
                string nodeContent = string.Empty;
                string nextNode    = string.Empty;

                nodeName = methodName + "_" + block.ToString();
                //nodeName = nodeName.Replace("-", "_");

                nodeContent += "<tr><td bgcolor=\"black\" align=\"center\" colspan=\"4\"><font face=\"Courier\" color=\"white\">L_" + block.Label.ToString("x4") + "</font></td></tr>";

                int field = 0;
                int i     = 0;

                for (Context ctx = new Context(InstructionSet, block); !ctx.EndOfInstruction; ctx.GotoNext())
                {
                    if (ctx.Instruction == null)
                    {
                        continue;
                    }

                    string color;
                    string inst = ctx.Instruction.ToString(ctx).Replace("&", "&amp;");
                    inst = inst.Replace("<", "&lt;");
                    inst = inst.Replace(">", "&gt;");

                    if (inst.StartsWith("IL") || inst.StartsWith("T_"))
                    {
                        color = "#0000ff5f";
                    }
                    else if (inst.StartsWith("IR"))
                    {
                        color = "#ff00005f";
                    }
                    else
                    {
                        color = "#CFD6CEff";
                    }


                    nodeContent += "<tr height=\"20\"><td bgcolor=\"white\" align=\"right\" width=\"20\"><img src=\"icon.png\"/></td><td bgcolor=\"white\" align=\"right\">" + (i++) + "</td><td bgcolor=\"" + color + "\" align=\"center\" colspan=\"2\"><font face=\"Courier\">" + inst + "</font></td></tr>";

                    ++field;
                }

                if (nodeContent != string.Empty && nodeContent[nodeContent.Length - 1] == '|')
                {
                    nodeContent = nodeContent.Substring(0, nodeContent.Length - 2);
                }

                if (nodeContent != string.Empty)
                {
                    nodes += "\"" + nodeName + "\" [label = <<table border=\"1\" cellborder=\"0\" cellpadding=\"3\" bgcolor=\"white\">" + nodeContent + "</table>> shape = \"Mrecord\"];\r\n";
                }


                foreach (BasicBlock nextBlock in block.NextBlocks)
                {
                    nextNode = methodName + "_" + nextBlock.ToString();

                    edges += "\"" + nodeName + "\"" + " -> " + "\"" + nextNode + "\";\r\n";
                }
            }

            dotFile.WriteLine(nodes);
            dotFile.WriteLine(edges);
            dotFile.WriteLine("};");
        }
        /// <summary>
        /// Finds all targets.
        /// </summary>
        /// <param name="index">The index.</param>
        private void SplitIntoBlocks(int index)
        {
            Dictionary<int, int> targets = new Dictionary<int, int>();

            targets.Add(index, -1);

            // Find out all targets labels
            for (Context ctx = new Context(InstructionSet, index); !ctx.EndOfInstruction; ctx.GotoNext())
            {
                switch (ctx.Instruction.FlowControl)
                {
                    case FlowControl.Next: continue;
                    case FlowControl.Call: continue;
                    case FlowControl.Break: goto case FlowControl.Branch;
                    case FlowControl.Return: continue;
                    case FlowControl.Throw: goto case FlowControl.Branch;
                    case FlowControl.Branch:
                        // Unconditional branch
                        Debug.Assert(ctx.Branch.Targets.Length == 1);
                        if (!targets.ContainsKey(ctx.Branch.Targets[0]))
                            targets.Add(ctx.Branch.Targets[0], -1);
                        continue;
                    case FlowControl.Switch: goto case FlowControl.ConditionalBranch;
                    case FlowControl.ConditionalBranch:
                        // Conditional branch with multiple targets
                        foreach (int target in ctx.Branch.Targets)
                            if (!targets.ContainsKey(target))
                                targets.Add(target, -1);
                        int next = ctx.Next.Label;
                        if (!targets.ContainsKey(next))
                            targets.Add(next, -1);
                        continue;
                    default:
                        Debug.Assert(false);
                        break;
                }
            }

            bool slice = false;

            for (Context ctx = new Context(InstructionSet, index); !ctx.EndOfInstruction; ctx.GotoNext())
            {
                FlowControl flow;

                if (targets.ContainsKey(ctx.Label))
                {
                    CreateBlock(ctx.Label, ctx.Index);

                    if (!ctx.IsFirstInstruction)
                    {
                        Context prev = ctx.Previous;
                        flow = prev.Instruction.FlowControl;
                        if (flow == FlowControl.Next || flow == FlowControl.Call || flow == FlowControl.ConditionalBranch || flow == FlowControl.Switch)
                        {
                            // This jump joins fall-through blocks, by giving them a proper end.
                            prev.AppendInstruction(CIL.Instruction.Get(CIL.OpCode.Br));
                            prev.SetBranch(ctx.Label);

                            prev.SliceAfter();
                        }
                    }

                    targets.Remove(ctx.Label);
                }

                if (slice)
                    ctx.SliceBefore();

                flow = ctx.Instruction.FlowControl;

                slice = (flow == FlowControl.Return || flow == FlowControl.Branch || flow == FlowControl.ConditionalBranch || flow == FlowControl.Break || flow == FlowControl.Throw);
            }

            Debug.Assert(targets.Count <= 1);

            if (FindBlock(0) == null)
                CreateBlock(0, index);
        }
        /// <summary>
        /// Called to emit a list of instructions offered by the instruction provider.
        /// </summary>
        protected virtual void EmitInstructions()
        {
            ExceptionClauseHeader exceptionClauseHeader = this.methodCompiler.Method.ExceptionClauseHeader;
            foreach (BasicBlock block in basicBlocks)
            {
                BlockStart(block);

                for (Context ctx = new Context(InstructionSet, block); !ctx.EndOfInstruction; ctx.GotoNext())
                    if (ctx.Instruction != null)
                        if (!ctx.Ignore)
                        {
                            if (block.ExceptionHeaderClause != null)
                            {
                                block.ExceptionHeaderClause.Update(ctx, codeStream);
                                block.ExceptionHeaderClause.AddLabelToCodeStream(codeEmitter);
                            }
                            IPlatformInstruction instruction = ctx.Instruction as IPlatformInstruction;
                            if (instruction != null)
                                instruction.Emit(ctx, codeEmitter);
                            else
                                Debug.WriteLine("Missing Code Transformation: " + ctx.ToString());
                        }

                BlockEnd(block);
            }
        }