void WriteStructureFooter(ILStructure s) { output.Unindent(); switch (s.Type) { case ILStructureType.Loop: output.WriteLine("// end loop"); break; case ILStructureType.Try: output.WriteLine("} // end .try"); break; case ILStructureType.Handler: output.WriteLine("} // end handler"); break; case ILStructureType.Filter: output.WriteLine("} // end filter"); break; default: throw new NotSupportedException(); } }
void WriteStructureHeader(ILStructure s) { switch (s.Type) { case ILStructureType.Loop: output.Write("// loop start"); if (s.LoopEntryPoint != null) { output.Write(" (head: "); DisassemblerHelpers.WriteOffsetReference(output, s.LoopEntryPoint); output.Write(')'); } output.WriteLine(); break; case ILStructureType.Try: output.WriteLine(".try"); output.WriteLine("{"); break; case ILStructureType.Handler: switch (s.ExceptionHandler.HandlerType) { case Mono.Cecil.Cil.ExceptionHandlerType.Catch: case Mono.Cecil.Cil.ExceptionHandlerType.Filter: output.Write("catch"); if (s.ExceptionHandler.CatchType != null) { output.Write(' '); s.ExceptionHandler.CatchType.WriteTo(output, ILNameSyntax.TypeName); } output.WriteLine(); break; case Mono.Cecil.Cil.ExceptionHandlerType.Finally: output.WriteLine("finally"); break; case Mono.Cecil.Cil.ExceptionHandlerType.Fault: output.WriteLine("fault"); break; default: throw new NotSupportedException(); } output.WriteLine("{"); break; case ILStructureType.Filter: output.WriteLine("filter"); output.WriteLine("{"); break; default: throw new NotSupportedException(); } output.Indent(); }
void WriteStructureBody(ILStructure s, HashSet <int> branchTargets, ref Instruction inst, MemberMapping currentMethodMapping, int codeSize) { bool isFirstInstructionInStructure = true; bool prevInstructionWasBranch = false; int childIndex = 0; while (inst != null && inst.Offset < s.EndOffset) { int offset = inst.Offset; if (childIndex < s.Children.Count && s.Children[childIndex].StartOffset <= offset && offset < s.Children[childIndex].EndOffset) { ILStructure child = s.Children[childIndex++]; WriteStructureHeader(child); WriteStructureBody(child, branchTargets, ref inst, currentMethodMapping, codeSize); WriteStructureFooter(child); } else { if (!isFirstInstructionInStructure && (prevInstructionWasBranch || branchTargets.Contains(offset))) { output.WriteLine(); // put an empty line after branches, and in front of branch targets } var startLocation = output.Location; inst.WriteTo(output); // add IL code mappings - used in debugger if (currentMethodMapping != null) { currentMethodMapping.MemberCodeMappings.Add( new SourceCodeMapping() { StartLocation = startLocation, EndLocation = output.Location, ILInstructionOffset = new ILRange { From = inst.Offset, To = inst.Next == null ? codeSize : inst.Next.Offset }, MemberMapping = currentMethodMapping }); } output.WriteLine(); prevInstructionWasBranch = inst.OpCode.FlowControl == FlowControl.Branch || inst.OpCode.FlowControl == FlowControl.Cond_Branch || inst.OpCode.FlowControl == FlowControl.Return || inst.OpCode.FlowControl == FlowControl.Throw; inst = inst.Next; } isFirstInstructionInStructure = false; } }
bool AddNestedStructure(ILStructure newStructure) { // special case: don't consider the loop-like structure of "continue;" statements to be nested loops if (this.Type == ILStructureType.Loop && newStructure.Type == ILStructureType.Loop && newStructure.StartOffset == this.StartOffset) { return(false); } // use <= for end-offset comparisons because both end and EndOffset are exclusive Debug.Assert(StartOffset <= newStructure.StartOffset && newStructure.EndOffset <= EndOffset); foreach (ILStructure child in this.Children) { if (child.StartOffset <= newStructure.StartOffset && newStructure.EndOffset <= child.EndOffset) { return(child.AddNestedStructure(newStructure)); } else if (!(child.EndOffset <= newStructure.StartOffset || newStructure.EndOffset <= child.StartOffset)) { // child and newStructure overlap if (!(newStructure.StartOffset <= child.StartOffset && child.EndOffset <= newStructure.EndOffset)) { // Invalid nesting, can't build a tree. -> Don't add the new structure. return(false); } } } // Move existing structures into the new structure: for (int i = 0; i < this.Children.Count; i++) { ILStructure child = this.Children[i]; if (newStructure.StartOffset <= child.StartOffset && child.EndOffset <= newStructure.EndOffset) { this.Children.RemoveAt(i--); newStructure.Children.Add(child); } } // Add the structure here: this.Children.Add(newStructure); return(true); }
bool AddNestedStructure(ILStructure newStructure) { // special case: don't consider the loop-like structure of "continue;" statements to be nested loops if (this.Type == ILStructureType.Loop && newStructure.Type == ILStructureType.Loop && newStructure.StartOffset == this.StartOffset) return false; // use <= for end-offset comparisons because both end and EndOffset are exclusive Debug.Assert(StartOffset <= newStructure.StartOffset && newStructure.EndOffset <= EndOffset); foreach (ILStructure child in this.Children) { if (child.StartOffset <= newStructure.StartOffset && newStructure.EndOffset <= child.EndOffset) { return child.AddNestedStructure(newStructure); } else if (!(child.EndOffset <= newStructure.StartOffset || newStructure.EndOffset <= child.StartOffset)) { // child and newStructure overlap if (!(newStructure.StartOffset <= child.StartOffset && child.EndOffset <= newStructure.EndOffset)) { // Invalid nesting, can't build a tree. -> Don't add the new structure. return false; } } } // Move existing structures into the new structure: for (int i = 0; i < this.Children.Count; i++) { ILStructure child = this.Children[i]; if (newStructure.StartOffset <= child.StartOffset && child.EndOffset <= newStructure.EndOffset) { this.Children.RemoveAt(i--); newStructure.Children.Add(child); } } // Add the structure here: this.Children.Add(newStructure); return true; }