BasicBlock[] IDominanceProvider.GetDominators(BasicBlock block) { if (block == null) throw new ArgumentNullException(@"block"); Debug.Assert(block.Sequence < _doms.Length, @"Invalid block index."); if (block.Sequence >= _doms.Length) throw new ArgumentException(@"Invalid block index.", @"block"); // Return value BasicBlock[] result; // Counter int count, idx = block.Sequence; // Count the dominators first for (count = 1; 0 != idx; count++) idx = _doms[idx].Sequence; // Allocate a dominator array result = new BasicBlock[count + 1]; result[0] = block; for (idx = block.Sequence, count = 1; 0 != idx; idx = _doms[idx].Sequence) result[count++] = _doms[idx]; result[count] = _doms[0]; return result; }
/// <summary> /// Performs stage specific processing on the compiler context. /// </summary> public void Run() { // Create the prologue block Context ctx = new Context(InstructionSet, -1); // Add a jump instruction to the first block from the prologue ctx.AppendInstruction(IR.Instruction.JmpInstruction); //ctx.AppendInstruction(CIL.Instruction.Get(CIL.OpCode.Br)); ctx.SetBranch(0); ctx.Label = -1; _prologue = CreateBlock(-1, ctx.Index); SplitIntoBlocks(0); // Create the epilogue block ctx = new Context(InstructionSet, -1); // Add null instruction, necessary to generate a block index ctx.AppendInstruction(null); ctx.Ignore = true; ctx.Label = Int32.MaxValue; _epilogue = CreateBlock(Int32.MaxValue, ctx.Index); // Link all the blocks together BuildBlockLinks(_prologue); // Link Exception Header Clauses LinkExceptionHeaderClauses(); }
/// <summary> /// Creates the block. /// </summary> /// <param name="label">The label.</param> /// <param name="index">The index.</param> /// <returns></returns> protected BasicBlock CreateBlock(int label, int index) { // HACK: BasicBlock.Count for the sequence works for now since blocks are not removed BasicBlock basicBlock = new BasicBlock (BasicBlocks.Count, label, index); BasicBlocks.Add (basicBlock); return basicBlock; }
BasicBlock[] IDominanceProvider.GetDominanceFrontierOfBlock(BasicBlock block) { if (block == null) throw new ArgumentNullException(@"block"); return _domFrontierOfBlock[block.Sequence]; }
/// <summary> /// Nexts the block has initial stack. /// </summary> /// <param name="block">The block.</param> /// <param name="nextBlock">The next block.</param> /// <returns></returns> private static bool NextBlockHasInitialStack(BasicBlock block, out BasicBlock nextBlock) { nextBlock = null; foreach (BasicBlock b in block.NextBlocks) { if (b.InitialStack == null) continue; nextBlock = b; return true; } return false; }
/// <summary> /// Initializes a new instance of the <see cref="Context"/> class. /// </summary> /// <param name="instructionSet">The instruction set.</param> /// <param name="basicBlock">The basic block.</param> public Context(InstructionSet instructionSet, BasicBlock basicBlock) { _instructionSet = instructionSet; _index = basicBlock.Index; _block = basicBlock; }
/// <summary> /// Sets the instruction. /// </summary> /// <param name="instruction">The instruction.</param> /// <param name="block">The block.</param> public void SetInstruction(IInstruction instruction, BasicBlock block) { SetInstruction(instruction); SetBranch(block); }
/// <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: { 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; } } }
private void FindAndLinkBlock(BasicBlock block, int target) { BasicBlock next = this.FindBlock(target); if (!block.NextBlocks.Contains(next)) { this.LinkBlocks(block, next); this.BuildBlockLinks(next); } }
/// <summary> /// Completion of code generation for a block. /// </summary> /// <param name="block">The completed block.</param> protected virtual void BlockEnd(BasicBlock block) { }
/// <summary> /// Creates the temporary moves. /// </summary> /// <param name="ctx">The CTX.</param> /// <param name="block">The block.</param> /// <param name="stack">The stack.</param> private void CreateTemporaryMoves(Context ctx, BasicBlock block, Stack<Operand> stack) { Context context = ctx.InsertBefore(); context.SetInstruction(IR.Instruction.NopInstruction); BasicBlock nextBlock; if (NextBlockHasInitialStack(block, out nextBlock)) LinkTemporaryMoves(context, block, nextBlock, stack); else CreateNewTemporaryMoves(context, block, stack); }
/// <summary> /// Inserts the instruction after. /// </summary> /// <param name="instruction">The instruction.</param> /// <param name="block">The block.</param> public void AppendInstruction(IInstruction instruction, BasicBlock block) { AppendInstruction(); SetInstruction(instruction, block); }
/// <summary> /// Determines the loop depths. /// </summary> private void DetermineLoopDepths() { // Create queue for first iteration Queue <ConnectedBlocks> queue = new Queue <ConnectedBlocks>(); queue.Enqueue(new ConnectedBlocks(null, _first)); // Flag per basic block Dictionary <BasicBlock, int> visited = new Dictionary <BasicBlock, int>(BasicBlocks.Count); Dictionary <BasicBlock, int> active = new Dictionary <BasicBlock, int>(BasicBlocks.Count); // Create dictionary for loop _header index assignments Dictionary <BasicBlock, int> loopHeaderIndexes = new Dictionary <BasicBlock, int>(); while (queue.Count != 0) { ConnectedBlocks at = queue.Dequeue(); if (active.ContainsKey(at.to)) { // Found a loop - // the loop-_header block is in at.to // and the loop-end is in at.From // Add loop-end to list _loops.Add(at); // Assign unique loop index (if not already set) if (!loopHeaderIndexes.ContainsKey(at.to)) { loopHeaderIndexes.Add(at.to, loopHeaderIndexes.Count); } // and continue iteration continue; } // Mark as active active.Add(at.to, 0); // Mark as visited visited.Add(at.to, 0); // Add successors to queue foreach (BasicBlock successor in at.to.NextBlocks) { queue.Enqueue(new ConnectedBlocks(at.to, successor)); } } // Create two-dimensional bit set of blocks belonging to loops //BitArray bitSet = new BitArray(loopHeaderIndexes.Count * BasicBlocks.Count, false); Dictionary <BasicBlock, List <BasicBlock> > count = new Dictionary <BasicBlock, List <BasicBlock> >(); // Create stack of Blocks for next step of iterations Stack <BasicBlock> stack = new Stack <BasicBlock>(); // Second set of iterations foreach (ConnectedBlocks loop in _loops) { // Add loop-tail to list List <BasicBlock> current; if (!count.ContainsKey(loop.to)) { current = new List <BasicBlock>(); current.Add(loop.to); count.Add(loop.to, current); } else { current = count[loop.to]; if (!current.Contains(loop.to)) { current.Add(loop.to); } } //Console.WriteLine(index.ToString() + " : B" + loop.to.Index.ToString()); // Add loop-end to stack stack.Push(loop.From); // Clear visit flag visited = new Dictionary <BasicBlock, int>(BasicBlocks.Count); while (stack.Count != 0) { BasicBlock at = stack.Pop(); // Already visited, continue loop if (visited.ContainsKey(at)) { continue; } // Mark as visisted if (!visited.ContainsKey(at)) { visited.Add(at, 0); } // Add predecessor to list (needed for count) if (!current.Contains(at)) { current.Add(at); } //Console.WriteLine(index.ToString() + " : B" + at.Index.ToString()); // Add predecessors to queue foreach (BasicBlock predecessor in at.PreviousBlocks) { if (predecessor != loop.to) // Exclude if Loop-Header { stack.Push(predecessor); } } } } // Last step, assign LoopIndex and LoopDepth to each basic block foreach (BasicBlock block in BasicBlocks) { if (count.ContainsKey(block)) { _depths.Add(block, count[block].Count); } else { _depths.Add(block, 0); } } }
/// <summary> /// Initializes a new instance of the <see cref="ConnectedBlocks"/> struct. /// </summary> /// <param name="from">From block.</param> /// <param name="to">To block.</param> public ConnectedBlocks(BasicBlock from, BasicBlock to) { this.to = to; this.From = from; }
/// <summary> /// Sets the branch. /// </summary> /// <param name="block">The block.</param> public void SetBranch(BasicBlock block) { SetBranch(block.Label); }
/// <summary> /// Inserts the instruction after. /// </summary> /// <param name="instruction">The instruction.</param> /// <param name="code">The code.</param> /// <param name="block">The block.</param> /// <param name="branchHint">if set to <c>true</c> [branch hint].</param> public void AppendInstruction(IInstruction instruction, IR.ConditionCode code, BasicBlock block, bool branchHint) { AppendInstruction(instruction, code, block); BranchHint = branchHint; }
/// <summary> /// Inserts the instruction after. /// </summary> /// <param name="instruction">The instruction.</param> /// <param name="code">The code.</param> /// <param name="block">The block.</param> public void AppendInstruction(IInstruction instruction, IR.ConditionCode code, BasicBlock block) { AppendInstruction(); SetInstruction(instruction, code, block); }
/// <summary> /// Sets the instruction. /// </summary> /// <param name="instruction">The instruction.</param> /// <param name="code">The code.</param> /// <param name="block">The block.</param> public void SetInstruction(IInstruction instruction, IR.ConditionCode code, BasicBlock block) { SetInstruction(instruction); ConditionCode = code; SetBranch(block); }
/// <summary> /// Links the temporary moves. /// </summary> /// <param name="ctx">The CTX.</param> /// <param name="block">The block.</param> /// <param name="nextBlock">The next block.</param> /// <param name="stack">The stack.</param> private void LinkTemporaryMoves(Context ctx, BasicBlock block, BasicBlock nextBlock, Stack<Operand> stack) { Stack<Operand> initialStack = GetCurrentStack(stack); Stack<Operand> nextInitialStack = GetCurrentStack(nextBlock.InitialStack); for (int i = 0; i < nextBlock.InitialStack.Count; ++i) ctx.AppendInstruction(IR.Instruction.MoveInstruction, nextInitialStack.Pop(), initialStack.Pop()); if (nextBlock.InitialStack.Count > 0) foreach (BasicBlock nBlock in block.NextBlocks) nBlock.InitialStack = GetCurrentStack(nextBlock.InitialStack); }
/// <summary> /// Initializes a new instance of the <see cref="Context"/> class. /// </summary> /// <param name="instructionSet">The instruction set.</param> /// <param name="index">The index.</param> public Context(InstructionSet instructionSet, int index) { _instructionSet = instructionSet; _index = index; _block = null; }
/// <summary> /// Determines whether [is not processed] [the specified block]. /// </summary> /// <param name="block">The block.</param> /// <returns> /// <c>true</c> if [is not processed] [the specified block]; otherwise, <c>false</c>. /// </returns> private bool IsNotProcessed(BasicBlock block) { return !_processed.Contains(block); }
BasicBlock IDominanceProvider.GetImmediateDominator(BasicBlock block) { if (block == null) throw new ArgumentNullException(@"block"); Debug.Assert(block.Sequence < _doms.Length, @"Invalid block index."); if (block.Sequence >= _doms.Length) throw new ArgumentException(@"Invalid block index.", @"block"); return _doms[block.Sequence]; }
/// <summary> /// Marks as processed. /// </summary> /// <param name="block">The block.</param> private void MarkAsProcessed(BasicBlock block) { if (_processed.Contains(block)) return; _processed.Add(block); }
/// <summary> /// Retrieves the highest common immediate dominator of the two given Blocks. /// </summary> /// <param name="b1">The first basic block.</param> /// <param name="b2">The second basic block.</param> /// <returns>The highest common dominator.</returns> private BasicBlock Intersect(BasicBlock b1, BasicBlock b2) { BasicBlock f1 = b1, f2 = b2; while (f2 != null && f1 != null && f1.Sequence != f2.Sequence) { while (f1 != null && f1.Sequence > f2.Sequence) f1 = _doms[f1.Sequence]; while (f2 != null && f1 != null && f2.Sequence > f1.Sequence) f2 = _doms[f2.Sequence]; } return f1; }
/// <summary> /// Start of code generation for a block. /// </summary> /// <param name="block">The started block.</param> protected virtual void BlockStart(BasicBlock block) { _codeEmitter.Label(block.Label); }
private BasicBlock[] ReversePostorder(List<BasicBlock> blocks) { BasicBlock[] result = new BasicBlock[blocks.Count - 1]; int idx = 0; Queue<BasicBlock> workList = new Queue<BasicBlock>(blocks.Count); // Add next blocks foreach (BasicBlock next in blocks[0].NextBlocks) workList.Enqueue(next); while (workList.Count != 0) { BasicBlock current = workList.Dequeue(); if (Array.IndexOf(result, current) == -1) { result[idx++] = current; foreach (BasicBlock next in current.NextBlocks) workList.Enqueue(next); } } return result; }
/// <summary> /// Spills all active operands at the end of a basic block. /// </summary> /// <param name="block">The basic block to spill in.</param> private void SpillActiveOperands(BasicBlock block) { int regIdx = 0; foreach (Operand op in _activeOperands) { if (op != null && op is MemoryOperand) { Context ctx = new Context(InstructionSet, block); ctx.GotoLast(); InsertMove(ctx, op, new RegisterOperand(op.Type, _registerSet[regIdx])); } regIdx++; } Array.Clear(_activeOperands, 0, _activeOperands.Length); }
/// <summary> /// Links the Blocks. /// </summary> /// <param name="caller">The caller.</param> /// <param name="callee">The callee.</param> private void LinkBlocks(BasicBlock caller, BasicBlock callee) { // Chain the blocks together caller.NextBlocks.Add(callee); callee.PreviousBlocks.Add(caller); }
/// <summary> /// Initializes a new instance of the <see cref="Context"/> class. /// </summary> /// <param name="instructionSet">The instruction set.</param> /// <param name="block">The block.</param> /// <param name="index">The index.</param> public Context(InstructionSet instructionSet, BasicBlock block, int index) { _instructionSet = instructionSet; _index = index; _block = block; }
/// <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("&", "&"); inst = inst.Replace("<", "<"); inst = inst.Replace(">", ">"); 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> /// 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); } }
/// <summary> /// Creates the new temporary moves. /// </summary> /// <param name="ctx">The CTX.</param> /// <param name="block">The block.</param> /// <param name="stack">The stack.</param> private void CreateNewTemporaryMoves(Context ctx, BasicBlock block, Stack<Operand> stack) { Stack<Operand> nextStack = new Stack<Operand>(); foreach (Operand operand in stack) { Operand temp = MethodCompiler.CreateTemporary(operand.Type); nextStack.Push(temp); _operandStack.Pop(); ctx.AppendInstruction(IR.Instruction.MoveInstruction, temp, operand); } if (nextStack.Count > 0) foreach (BasicBlock nextBlock in block.NextBlocks) nextBlock.InitialStack = GetCurrentStack(nextStack); }
/// <summary> /// Sets the instruction. /// </summary> /// <param name="instruction">The instruction.</param> /// <param name="code">The code.</param> /// <param name="block">The block.</param> /// <param name="branchHint">if set to <c>true</c> [branch hint].</param> public void SetInstruction(IInstruction instruction, IR.ConditionCode code, BasicBlock block, bool branchHint) { SetInstruction(instruction, code, block); BranchHint = branchHint; }