diff --git a/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs b/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs index 61756612f..dea38d3c9 100644 --- a/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs +++ b/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs @@ -1,8 +1,11 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Text; using Decompiler.ControlFlow; +using ICSharpCode.Decompiler; +using ICSharpCode.Decompiler.Disassembler; using Mono.Cecil; using Mono.Cecil.Cil; using Cecil = Mono.Cecil; @@ -45,10 +48,14 @@ namespace Decompiler yield break; } - public override string ToString() - { - return this.GetType().Name; + public override string ToString() + { + StringWriter w = new StringWriter(); + WriteTo(new PlainTextOutput(w)); + return w.ToString(); } + + public abstract void WriteTo(ITextOutput output); } public class ILBlock: ILNode @@ -75,15 +82,24 @@ namespace Decompiler yield return child; } } + + public override void WriteTo(ITextOutput output) + { + EntryPoint.WriteTo(output); + foreach(ILNode child in this.Body) { + child.WriteTo(output); + output.WriteLine(); + } + } } public class ILLabel: ILNode { public string Name; - public override string ToString() + public override void WriteTo(ITextOutput output) { - return Name + ":"; + output.WriteDefinition(Name + ":", this); } } @@ -92,6 +108,15 @@ namespace Decompiler public class CatchBlock: ILBlock { public TypeReference ExceptionType; + + public override void WriteTo(ITextOutput output) + { + output.Write("catch "); + output.WriteReference(ExceptionType.FullName, ExceptionType); + output.WriteLine(" {"); + base.WriteTo(output); + output.WriteLine("}"); + } } public ILBlock TryBlock; @@ -107,6 +132,21 @@ namespace Decompiler if (this.FinallyBlock != null) yield return this.FinallyBlock; } + + public override void WriteTo(ITextOutput output) + { + output.WriteLine(".try {"); + TryBlock.WriteTo(output); + output.WriteLine("}"); + foreach (CatchBlock block in CatchBlocks) { + block.WriteTo(output); + } + if (FinallyBlock != null) { + output.WriteLine("finally {"); + FinallyBlock.WriteTo(output); + output.WriteLine("}"); + } + } } public class ILVariable @@ -185,23 +225,35 @@ namespace Decompiler return Arguments; } - public override string ToString() + public override void WriteTo(ITextOutput output) { - StringBuilder sb = new StringBuilder(); - sb.Append(OpCode.Name); - sb.Append('('); + if (Operand is ILVariable && ((ILVariable)Operand).IsGenerated) { + if (OpCode.Name == "stloc") { + output.Write(((ILVariable)Operand).Name + " = "); + Arguments.First().WriteTo(output); + return; + } else if (OpCode.Name == "ldloc") { + output.Write(((ILVariable)Operand).Name); + return; + } + } + + output.Write(OpCode.Name); + output.Write('('); bool first = true; if (Operand != null) { - sb.Append(Operand.ToString()); + if (Operand is ILLabel) + output.Write(((ILLabel)Operand).Name); + else + DisassemblerHelpers.WriteOperand(output, Operand); first = false; } foreach (ILExpression arg in this.Arguments) { - if (!first) sb.Append(","); - sb.Append(arg.ToString()); + if (!first) output.Write(','); + arg.WriteTo(output); first = false; } - sb.Append(')'); - return sb.ToString(); + output.Write(')'); } } @@ -213,6 +265,15 @@ namespace Decompiler { yield return ContentBlock; } + + public override void WriteTo(ITextOutput output) + { + output.WriteLine("loop {"); + output.Indent(); + ContentBlock.WriteTo(output); + output.Unindent(); + output.WriteLine("}"); + } } public class ILCondition: ILNode @@ -227,6 +288,24 @@ namespace Decompiler yield return TrueBlock; yield return FalseBlock; } + + public override void WriteTo(ITextOutput output) + { + output.Write("if ("); + Condition.WriteTo(output); + output.WriteLine(") {"); + output.Indent(); + TrueBlock.WriteTo(output); + output.Unindent(); + output.Write("}"); + if (FalseBlock != null) { + output.WriteLine(" else {"); + output.Indent(); + FalseBlock.WriteTo(output); + output.Unindent(); + output.WriteLine("}"); + } + } } public class ILSwitch: ILNode @@ -241,5 +320,21 @@ namespace Decompiler yield return caseBlock; } } + + public override void WriteTo(ITextOutput output) + { + output.Write("switch ("); + Condition.WriteTo(output); + output.WriteLine(") {"); + output.Indent(); + for (int i = 0; i < CaseBlocks.Count; i++) { + output.WriteLine("case {0}:", i); + output.Indent(); + CaseBlocks[i].WriteTo(output); + output.Unindent(); + } + output.Unindent(); + output.WriteLine("}"); + } } -} +} \ No newline at end of file diff --git a/ILSpy/ILAstLanguage.cs b/ILSpy/ILAstLanguage.cs new file mode 100644 index 000000000..34fd5a037 --- /dev/null +++ b/ILSpy/ILAstLanguage.cs @@ -0,0 +1,65 @@ +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Decompiler; +using Decompiler.Transforms; +using ICSharpCode.Decompiler; +using ICSharpCode.NRefactory.CSharp; +using Mono.Cecil; + +namespace ICSharpCode.ILSpy +{ + /// <summary> + /// Represents the ILAst "language" used for debugging purposes. + /// </summary> + public class ILAstLanguage : Language + { + public override string Name { + get { + return "ILAst"; + } + } + + public override void DecompileMethod(MethodDefinition method, ITextOutput output, DecompilationOptions options) + { + var body = new ILAstBuilder().Build(method, false); + + foreach (ILNode node in body) { + node.WriteTo(output); + output.WriteLine(); + } + } + + #if DEBUG + internal static IEnumerable<ILAstLanguage> GetDebugLanguages() + { + yield return new ILAstLanguage(); + } + #endif + + public override string FileExtension { + get { + return ".il"; + } + } + } +} diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj index 96ba3f047..984338654 100644 --- a/ILSpy/ILSpy.csproj +++ b/ILSpy/ILSpy.csproj @@ -95,6 +95,7 @@ <Compile Include="Fusion.cs" /> <Compile Include="GacInterop.cs" /> <Compile Include="GuessFileType.cs" /> + <Compile Include="ILAstLanguage.cs" /> <Compile Include="ILLanguage.cs" /> <Compile Include="ILSpySettings.cs" /> <Compile Include="ISmartTextOutput.cs" /> diff --git a/ILSpy/Language.cs b/ILSpy/Language.cs index ea4306dc7..5a96521b0 100644 --- a/ILSpy/Language.cs +++ b/ILSpy/Language.cs @@ -126,6 +126,7 @@ namespace ICSharpCode.ILSpy new ILLanguage(true) } #if DEBUG + .Concat(ILAstLanguage.GetDebugLanguages()) .Concat(CSharpLanguage.GetDebugLanguages()) #endif ).AsReadOnly();