/// <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(); } } }
/// <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++; }
/// <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++; } } }