Exemplo n.º 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);
 }
 /// <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);
             }
         }
     }
 }
        /// <summary>
        /// Splits the block.
        /// </summary>
        /// <param name="ctx">The context.</param>
        /// <param name="addJump">if set to <c>true</c> [add jump].</param>
        /// <returns></returns>
        protected Context SplitContext(Context ctx, bool addJump)
        {
            Context current = ctx.Clone();

            int label = basicBlocks.Count + 0x10000000;

            BasicBlock nextBlock = CreateBlock(label);

            foreach (BasicBlock block in current.BasicBlock.NextBlocks)
            {
                nextBlock.NextBlocks.Add(block);
            }

            current.BasicBlock.NextBlocks.Clear();

            if (addJump)
            {
                current.BasicBlock.NextBlocks.Add(nextBlock);
                nextBlock.PreviousBlocks.Add(ctx.BasicBlock);
            }

            if (current.IsLastInstruction)
            {
                current.AppendInstruction(null);
                current.Ignore  = true;
                nextBlock.Index = current.Index;
                current.SliceBefore();
            }
            else
            {
                nextBlock.Index = current.Next.Index;
                current.SliceAfter();
            }

            if (addJump)
            {
                current.AppendInstruction(IR.Instruction.JmpInstruction, nextBlock);
            }

            return(CreateContext(nextBlock));
        }
        /// <summary>
        /// Assigns registers to operands of the instruction.
        /// </summary>
        /// <param name="ctx">The context.</param>
        private void AssignRegisters(Context ctx)
        {
            // Retrieve the register constraints for the instruction
            IRegisterConstraint rc = null; // _architecture.GetRegisterConstraint(instr);	// FIXME PG - pass context instead???

            // Operand index
            int opIdx;

            if (rc == null && TRACING.TraceWarning)
                Trace.WriteLine(String.Format(@"Failed to get register constraints for instruction {0}!", ctx.Instruction.ToString(ctx)));

            // Only process the instruction, if we have constraints...
            if (rc != null) {
                /* FIXME: Spill used registers, if they are in use :(
                 * It is not as simple as it sounds, as the register may be used by the instruction itself,
                 * but dirty afterwards anyways. So we need to decide this at some later point depending on
                 * the arg list. If the register is also a result reg, and they represent the same operand,
                 * we may get away without spilling... Oo?
                 */
                //Register[] used = rc.GetRegistersUsed();

                opIdx = 0;

                Context at = ctx.Clone();

                foreach (Operand op in ctx.Operands) {
                    // Only allocate registers, if we really have to.
                    if (!rc.IsValidOperand(opIdx, op)) {
                        // The register operand allocated
                        RegisterOperand rop;
                        // List of compatible registers
                        Register[] regs = rc.GetRegistersForOperand(opIdx);
                        Debug.Assert(null != regs, @"IRegisterConstraint.GetRegistersForOperand returned null.");
                        Debug.Assert(0 != regs.Length, @"WTF IRegisterConstraint.GetRegistersForOperand returned zero-length array - what shall we pass then if no register/memory?");

                        // Is this operand in a register?
                        rop = GetRegisterOfOperand(op);
                        if (rop != null && Array.IndexOf(regs, rop.Register) == -1) {
                            // Spill the register...
                            SpillRegister(ctx, op, rop);
                            rop = null;
                        }

                        // Attempt to allocate a free register
                        if (rop == null) {
                            rop = AllocateRegister(regs, op);
                            if (rop != null) {
                                // We need to place a load here... :(
                                InsertMove(ctx, rop, op);
                            }
                        }

                        // Still failed to get one? Spill!
                        if (rop == null) {
                            // Darn, need to spill one... Always use the first one.
                            rop = SpillRegister(at, op.Type, regs);

                            // We need to place a load here... :(
                            InsertMove(at, rop, op);
                        }

                        // Assign the register
                        Debug.Assert(rop != null, @"Whoa: Failed to allocate a register operand??");
                        AssignRegister(rop, op, at);
                        ctx.SetOperand(opIdx, rop); // FIXME PG - opIdx? hmmm. is this phidata?
                    }

                    opIdx++;
                }

                opIdx = 0;
                foreach (Operand res in ctx.Results) {
                    // FIXME: Check support first, spill if register is target and in use
                    if (!rc.IsValidResult(opIdx, res)) {
                        // Is this operand in a register?
                        RegisterOperand rop = GetRegisterOfOperand(res);
                        if (rop == null && !rc.IsValidResult(opIdx, res) && res.Uses.Count == 0)
                            // Do not allocate: Not in a register, allows memory & has no uses... oO wtf?
                            continue;

                        // Retrieve compliant registers
                        Register[] regs = rc.GetRegistersForResult(opIdx);

                        // Do we already have a register?
                        if (rop != null && Array.IndexOf(regs, rop.Register) == -1) {
                            // Hmm, current register doesn't match, release it - since we're overwriting the operand,
                            // we don't need to spill. This should be safe.
                            _activeOperands[rop.Register.Index] = null;
                        }

                        // Allocate a register
                        if (rop == null)
                            rop = AllocateRegister(regs, res);

                        // Do we need to spill?
                        if (rop == null) {
                            // Darn, need to spill one...
                            rop = SpillRegister(at, res.Type, regs);
                            // We don't need to place a load here, as we're defining the register...
                        }

                        // Assign the register
                        Debug.Assert(null != rop, @"Whoa: Failed to allocate a register operand??");
                        AssignRegister(rop, res, at);
                        ctx.SetResult(opIdx, rop); // FIXME PG - same
                    }
                    else {
                        RegisterOperand rop = res as RegisterOperand;
                        if (rop != null)
                            SpillRegisterIfInUse(ctx, rop);
                    }

                    opIdx++;
                }
            }
        }
        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();
                }
            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// Splits the block.
        /// </summary>
        /// <param name="ctx">The context.</param>
        /// <param name="addJump">if set to <c>true</c> [add jump].</param>
        /// <returns></returns>
        protected Context SplitContext(Context ctx, bool addJump)
        {
            Context current = ctx.Clone ();

            int label = BasicBlocks.Count + 0x10000000;

            BasicBlock nextBlock = CreateBlock (label);

            foreach (BasicBlock block in current.BasicBlock.NextBlocks)
                nextBlock.NextBlocks.Add (block);

            current.BasicBlock.NextBlocks.Clear ();

            if (addJump)
            {
                current.BasicBlock.NextBlocks.Add (nextBlock);
                nextBlock.PreviousBlocks.Add (ctx.BasicBlock);
            }

            if (current.IsLastInstruction)
            {
                current.AppendInstruction (null);
                current.Ignore = true;
                nextBlock.Index = current.Index;
                current.SliceBefore ();
            } else
            {
                nextBlock.Index = current.Next.Index;
                current.SliceAfter ();
            }

            if (addJump)
                current.AppendInstruction (IR.Instruction.JmpInstruction, nextBlock);

            return CreateContext (nextBlock);
        }
            /// <summary>
            /// Nexts the specified CTX.
            /// </summary>
            /// <param name="ctx">The CTX.</param>
            public void Add(Context ctx)
            {
                for (int i = _length - 1; i > 0; i--)
                    _history[i] = _history[i - 1];

                _history[0] = ctx.Clone();
                if (_size < _length)
                    _size++;
            }
Exemplo n.º 8
0
        /// <summary>
        /// Assigns registers to operands of the instruction.
        /// </summary>
        /// <param name="ctx">The context.</param>
        private void AssignRegisters(Context ctx)
        {
            // Retrieve the register constraints for the instruction
            IRegisterConstraint rc = null;             // _architecture.GetRegisterConstraint(instr);	// FIXME PG - pass context instead???

            // Operand index
            int opIdx;

            if (rc == null && TRACING.TraceWarning)
            {
                Trace.WriteLine(String.Format(@"Failed to get register constraints for instruction {0}!", ctx.Instruction.ToString(ctx)));
            }

            // Only process the instruction, if we have constraints...
            if (rc != null)
            {
                /* FIXME: Spill used registers, if they are in use :(
                 * It is not as simple as it sounds, as the register may be used by the instruction itself,
                 * but dirty afterwards anyways. So we need to decide this at some later point depending on
                 * the arg list. If the register is also a result reg, and they represent the same operand,
                 * we may get away without spilling... Oo?
                 */
                //Register[] used = rc.GetRegistersUsed();

                opIdx = 0;

                Context at = ctx.Clone();

                foreach (Operand op in ctx.Operands)
                {
                    // Only allocate registers, if we really have to.
                    if (!rc.IsValidOperand(opIdx, op))
                    {
                        // The register operand allocated
                        RegisterOperand rop;
                        // List of compatible registers
                        Register[] regs = rc.GetRegistersForOperand(opIdx);
                        Debug.Assert(null != regs, @"IRegisterConstraint.GetRegistersForOperand returned null.");
                        Debug.Assert(0 != regs.Length, @"WTF IRegisterConstraint.GetRegistersForOperand returned zero-length array - what shall we pass then if no register/memory?");

                        // Is this operand in a register?
                        rop = GetRegisterOfOperand(op);
                        if (rop != null && Array.IndexOf(regs, rop.Register) == -1)
                        {
                            // Spill the register...
                            SpillRegister(ctx, op, rop);
                            rop = null;
                        }

                        // Attempt to allocate a free register
                        if (rop == null)
                        {
                            rop = AllocateRegister(regs, op);
                            if (rop != null)
                            {
                                // We need to place a load here... :(
                                InsertMove(ctx, rop, op);
                            }
                        }

                        // Still failed to get one? Spill!
                        if (rop == null)
                        {
                            // Darn, need to spill one... Always use the first one.
                            rop = SpillRegister(at, op.Type, regs);

                            // We need to place a load here... :(
                            InsertMove(at, rop, op);
                        }

                        // Assign the register
                        Debug.Assert(rop != null, @"Whoa: Failed to allocate a register operand??");
                        AssignRegister(rop, op, at);
                        ctx.SetOperand(opIdx, rop);                         // FIXME PG - opIdx? hmmm. is this phidata?
                    }

                    opIdx++;
                }

                opIdx = 0;
                foreach (Operand res in ctx.Results)
                {
                    // FIXME: Check support first, spill if register is target and in use
                    if (!rc.IsValidResult(opIdx, res))
                    {
                        // Is this operand in a register?
                        RegisterOperand rop = GetRegisterOfOperand(res);
                        if (rop == null && !rc.IsValidResult(opIdx, res) && res.Uses.Count == 0)
                        {
                            // Do not allocate: Not in a register, allows memory & has no uses... oO wtf?
                            continue;
                        }

                        // Retrieve compliant registers
                        Register[] regs = rc.GetRegistersForResult(opIdx);

                        // Do we already have a register?
                        if (rop != null && Array.IndexOf(regs, rop.Register) == -1)
                        {
                            // Hmm, current register doesn't match, release it - since we're overwriting the operand,
                            // we don't need to spill. This should be safe.
                            _activeOperands[rop.Register.Index] = null;
                        }

                        // Allocate a register
                        if (rop == null)
                        {
                            rop = AllocateRegister(regs, res);
                        }

                        // Do we need to spill?
                        if (rop == null)
                        {
                            // Darn, need to spill one...
                            rop = SpillRegister(at, res.Type, regs);
                            // We don't need to place a load here, as we're defining the register...
                        }

                        // Assign the register
                        Debug.Assert(null != rop, @"Whoa: Failed to allocate a register operand??");
                        AssignRegister(rop, res, at);
                        ctx.SetResult(opIdx, rop);                         // FIXME PG - same
                    }
                    else
                    {
                        RegisterOperand rop = res as RegisterOperand;
                        if (rop != null)
                        {
                            SpillRegisterIfInUse(ctx, rop);
                        }
                    }

                    opIdx++;
                }
            }
        }