/// <summary> /// Performs stage specific processing on the compiler context. /// </summary> public void Run() { // Previous stage IPipelineStage prevStage = MethodCompiler.GetPreviousStage(typeof(IMethodCompilerStage)); // Line number int index = 1; Debug.WriteLine(String.Format("IR representation of method {0} after stage {1}", MethodCompiler.Method, prevStage.Name)); foreach (BasicBlock block in BasicBlocks) { Debug.WriteLine(String.Format("Block #{0} - label L_{1:X4}", index, block.Label)); foreach (BasicBlock prev in block.PreviousBlocks) { Debug.WriteLine(String.Format(" Prev: L_{0:X4}", prev.Label)); } Debug.Indent(); LogInstructions(new Context(InstructionSet, block)); Debug.Unindent(); foreach (BasicBlock next in block.NextBlocks) { Debug.WriteLine(String.Format(" Next: L_{0:X4}", next.Label)); } index++; } }
/// <summary> /// Performs stage specific processing on the compiler context. /// </summary> public void Run() { _dominanceProvider = (IDominanceProvider)MethodCompiler.GetPreviousStage(typeof(IDominanceProvider)); Debug.Assert(_dominanceProvider != null, "SSA Conversion requires a dominance provider."); if (_dominanceProvider == null) { throw new InvalidOperationException("SSA Conversion requires a dominance provider."); } // Allocate space for live outs _liveness = new IDictionary <StackOperand, StackOperand> [BasicBlocks.Count]; // Retrieve the dominance frontier Blocks _dominanceFrontierBlocks = _dominanceProvider.GetDominanceFrontier(); // Add ref/out parameters to the epilogue block to have uses there... AddPhiFunctionsForOutParameters(); // Transformation worklist Queue <WorkItem> workList = new Queue <WorkItem> (); /* Move parameter operands into the dictionary as version 0, * because they are live at entry and maybe referenced. Anyways, an * assignment to a parameter is also SSA related. */ IDictionary <StackOperand, StackOperand> liveIn = new Dictionary <StackOperand, StackOperand> (s_comparer); int i = 0; if (MethodCompiler.Method.Signature.HasThis) { StackOperand param = (StackOperand)MethodCompiler.GetParameterOperand(0); liveIn.Add(param, param); i++; } for (int j = 0; j < MethodCompiler.Method.Parameters.Count; j++) { StackOperand param = (StackOperand)MethodCompiler.GetParameterOperand(i + j); liveIn.Add(param, param); } // Start with the very first block workList.Enqueue(new WorkItem(BasicBlocks[0], null, liveIn)); // Iterate until the worklist is empty while (workList.Count != 0) { // Remove the block From the queue WorkItem workItem = workList.Dequeue(); // Transform the block BasicBlock block = workItem.block; bool schedule = TransformToSsaForm(new Context(InstructionSet, block), workItem.caller, workItem.liveIn, out liveIn); _liveness[block.Sequence] = liveIn; if (schedule) { // Add all branch targets to the work list foreach (BasicBlock next in block.NextBlocks) { // Only follow backward branches, if we've redefined a variable // this may force us to reinsert a PHI function in a block we // already have completed processing on. workList.Enqueue(new WorkItem(next, block, liveIn)); } } } }
/// <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("};"); }