Browse Source

Create ILFunction top-level node

pull/728/head
Daniel Grunwald 11 years ago
parent
commit
63b32fef35
  1. 4
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  2. 2
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  3. 37
      ICSharpCode.Decompiler/IL/BlockBuilder.cs
  4. 14
      ICSharpCode.Decompiler/IL/ILReader.cs
  5. 12
      ICSharpCode.Decompiler/IL/ILVariable.cs
  6. 34
      ICSharpCode.Decompiler/IL/Instructions.cs
  7. 4
      ICSharpCode.Decompiler/IL/Instructions.tt
  8. 27
      ICSharpCode.Decompiler/IL/Instructions/Block.cs
  9. 36
      ICSharpCode.Decompiler/IL/Instructions/BlockContainer.cs
  10. 59
      ICSharpCode.Decompiler/IL/Instructions/Branch.cs
  11. 69
      ICSharpCode.Decompiler/IL/Instructions/ILFunction.cs
  12. 15
      ICSharpCode.Decompiler/IL/Instructions/InstructionCollection.cs
  13. 20
      ICSharpCode.Decompiler/IL/Instructions/MemoryInstructions.cs
  14. 64
      ICSharpCode.Decompiler/IL/TransformingVisitor.cs
  15. 8
      ILSpy/Languages/ILAstLanguage.cs

4
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -102,8 +102,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -102,8 +102,8 @@ namespace ICSharpCode.Decompiler.CSharp
var entityDecl = typeSystemAstBuilder.ConvertEntity(method);
if (methodDefinition.HasBody) {
var ilReader = new ILReader(methodDefinition.Body, CancellationToken);
var inst = ilReader.CreateBlocks(true);
var body = statementBuilder.ConvertAsBlock(inst);
var function = ilReader.CreateFunction(true);
var body = statementBuilder.ConvertAsBlock(function.Body);
body.AcceptVisitor(new InsertParenthesesVisitor { InsertParenthesesForReadability = true });
entityDecl.AddChild(body, Roles.Body);
}

2
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -79,6 +79,7 @@ @@ -79,6 +79,7 @@
<Compile Include="IL\Instructions\CallInstruction.cs" />
<Compile Include="IL\Instructions\Conv.cs" />
<Compile Include="IL\Instructions\IfInstruction.cs" />
<Compile Include="IL\Instructions\ILFunction.cs" />
<Compile Include="IL\Instructions\ILInstruction.cs" />
<Compile Include="IL\Instructions\InstructionCollection.cs" />
<Compile Include="IL\Instructions\MemoryInstructions.cs" />
@ -87,6 +88,7 @@ @@ -87,6 +88,7 @@
<Compile Include="IL\Instructions\TryCatch.cs" />
<Compile Include="IL\Instructions\TryFinally.cs" />
<Compile Include="IL\Instructions\UnaryInstruction.cs" />
<Compile Include="IL\TransformingVisitor.cs" />
<Compile Include="TypesHierarchyHelpers.cs" />
<Compile Include="CecilExtensions.cs" />
<Compile Include="Disassembler\DisassemblerHelpers.cs" />

37
ICSharpCode.Decompiler/IL/BlockBuilder.cs

@ -43,7 +43,6 @@ namespace ICSharpCode.Decompiler.IL @@ -43,7 +43,6 @@ namespace ICSharpCode.Decompiler.IL
public BlockContainer CreateBlocks(List<ILInstruction> instructions, BitArray incomingBranches)
{
currentContainer = new BlockContainer();
currentContainer.AddRef(); // mark the root node
incomingBranches[0] = true; // see entrypoint as incoming branch
@ -95,6 +94,7 @@ namespace ICSharpCode.Decompiler.IL @@ -95,6 +94,7 @@ namespace ICSharpCode.Decompiler.IL
}
}
FinalizeCurrentBlock(body.CodeSize, fallthrough: false);
ConnectBranches(currentContainer);
return currentContainer;
}
@ -117,5 +117,40 @@ namespace ICSharpCode.Decompiler.IL @@ -117,5 +117,40 @@ namespace ICSharpCode.Decompiler.IL
instructionStack.Clear();
}
}
Stack<BlockContainer> containerStack = new Stack<BlockContainer>();
void ConnectBranches(ILInstruction inst)
{
switch (inst.OpCode) {
case OpCode.Branch:
var branch = (Branch)inst;
branch.TargetBlock = FindBranchTarget(branch.TargetILOffset);
break;
case OpCode.BlockContainer:
var container = (BlockContainer)inst;
containerStack.Push(container);
container.EntryPoint.IncomingEdgeCount++; // count the entry edge
foreach (var block in container.Blocks)
ConnectBranches(block);
containerStack.Pop();
break;
default:
foreach (var child in inst.Children)
ConnectBranches(child);
break;
}
}
Block FindBranchTarget(int targetILOffset)
{
foreach (var container in containerStack) {
foreach (var block in container.Blocks) {
if (block.ILRange.Start == targetILOffset)
return block;
}
}
throw new InvalidOperationException("Could not find block for branch target");
}
}
}

14
ICSharpCode.Decompiler/IL/ILReader.cs

@ -169,16 +169,16 @@ namespace ICSharpCode.Decompiler.IL @@ -169,16 +169,16 @@ namespace ICSharpCode.Decompiler.IL
new Disassembler.MethodBodyDisassembler(output, false, cancellationToken).WriteExceptionHandlers(body);
}
public void WriteBlocks(ITextOutput output, bool instructionInlining)
{
CreateBlocks(instructionInlining).WriteTo(output);
}
internal BlockContainer CreateBlocks(bool instructionInlining)
public ILFunction CreateFunction(bool instructionInlining)
{
if (instructionBuilder == null)
ReadInstructions(null);
return new BlockBuilder(body, instructionInlining).CreateBlocks(instructionBuilder, isBranchTarget);
var container = new BlockBuilder(body, instructionInlining).CreateBlocks(instructionBuilder, isBranchTarget);
var function = new ILFunction(body.Method, container);
function.Variables.AddRange(parameterVariables);
function.Variables.AddRange(localVariables);
function.AddRef(); // mark the root node
return function;
}
ILInstruction Neg()

12
ICSharpCode.Decompiler/IL/ILVariable.cs

@ -23,6 +23,7 @@ using System.Collections.Generic; @@ -23,6 +23,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ICSharpCode.Decompiler.Disassembler;
namespace ICSharpCode.Decompiler.IL
{
@ -78,10 +79,17 @@ namespace ICSharpCode.Decompiler.IL @@ -78,10 +79,17 @@ namespace ICSharpCode.Decompiler.IL
return Kind.ToString();
}
}
internal void WriteDefinitionTo(ITextOutput output)
{
output.WriteDefinition(this.Name, CecilObject ?? this, isLocal: true);
output.Write(" : ");
Type.WriteTo(output);
}
internal void WriteTo(ITextOutput output)
{
output.WriteReference(this.ToString(), CecilObject ?? this, isLocal: true);
output.WriteReference(this.Name, CecilObject ?? this, isLocal: true);
}
}
}

34
ICSharpCode.Decompiler/IL/Instructions.cs

@ -36,6 +36,8 @@ namespace ICSharpCode.Decompiler.IL @@ -36,6 +36,8 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Ignore the arguments and produce void. Used to prevent the end result of an instruction from being pushed to the evaluation stack.</summary>
Void,
/// <summary>A container of IL blocks.</summary>
ILFunction,
/// <summary>A container of IL blocks.</summary>
BlockContainer,
/// <summary>A block of IL instructions.</summary>
Block,
@ -328,6 +330,33 @@ namespace ICSharpCode.Decompiler.IL @@ -328,6 +330,33 @@ namespace ICSharpCode.Decompiler.IL
}
}
/// <summary>A container of IL blocks.</summary>
public sealed partial class ILFunction : ILInstruction
{
ILInstruction body;
public ILInstruction Body {
get { return this.body; }
set {
ValidateChild(value);
SetChildInstruction(ref this.body, value);
}
}
public override IEnumerable<ILInstruction> Children {
get {
yield return this.body;
}
}
public override void TransformChildren(ILVisitor<ILInstruction> visitor)
{
this.Body = this.body.AcceptVisitor(visitor);
}
public override StackType ResultType { get { return StackType.O; } }
public override T AcceptVisitor<T>(ILVisitor<T> visitor)
{
return visitor.VisitILFunction(this);
}
}
/// <summary>A container of IL blocks.</summary>
public sealed partial class BlockContainer : ILInstruction
{
@ -2037,6 +2066,10 @@ namespace ICSharpCode.Decompiler.IL @@ -2037,6 +2066,10 @@ namespace ICSharpCode.Decompiler.IL
{
return Default(inst);
}
protected internal virtual T VisitILFunction(ILFunction function)
{
return Default(function);
}
protected internal virtual T VisitBlockContainer(BlockContainer container)
{
return Default(container);
@ -2362,6 +2395,7 @@ namespace ICSharpCode.Decompiler.IL @@ -2362,6 +2395,7 @@ namespace ICSharpCode.Decompiler.IL
"pop",
"peek",
"void",
"ILFunction",
"BlockContainer",
"Block",
"logic.not",

4
ICSharpCode.Decompiler/IL/Instructions.tt

@ -39,6 +39,10 @@ @@ -39,6 +39,10 @@
Peeking, NoArguments, ResultTypeParam),
new OpCode("void", "Ignore the arguments and produce void. Used to prevent the end result of an instruction from being pushed to the evaluation stack.",
VoidResult, Unary),
new OpCode("ILFunction", "A container of IL blocks.",
CustomChildren(new [] {
new ChildInfo("body")
}), CustomConstructor, CustomWriteTo, CustomComputeFlags, CustomVariableName("function"), ResultType("O")),
new OpCode("BlockContainer", "A container of IL blocks.",
VoidResult, CustomConstructor, CustomVariableName("container")),
new OpCode("Block", "A block of IL instructions.",

27
ICSharpCode.Decompiler/IL/Instructions/Block.cs

@ -1,4 +1,22 @@ @@ -1,4 +1,22 @@
using System;
// Copyright (c) 2014 Daniel Grunwald
//
// 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.Diagnostics;
using System.Linq;
@ -11,6 +29,8 @@ namespace ICSharpCode.Decompiler.IL @@ -11,6 +29,8 @@ namespace ICSharpCode.Decompiler.IL
{
public readonly InstructionCollection<ILInstruction> Instructions;
public int IncomingEdgeCount;
public Block() : base(OpCode.Block)
{
this.Instructions = new InstructionCollection<ILInstruction>(this);
@ -32,7 +52,10 @@ namespace ICSharpCode.Decompiler.IL @@ -32,7 +52,10 @@ namespace ICSharpCode.Decompiler.IL
public override void WriteTo(ITextOutput output)
{
output.WriteDefinition("Block " + Label, this);
output.Write("Block ");
output.WriteDefinition(Label, this);
if (Parent is BlockContainer)
output.Write(" (incoming: {0})", IncomingEdgeCount);
output.WriteLine(" {");
output.Indent();
foreach (var inst in Instructions) {

36
ICSharpCode.Decompiler/IL/Instructions/BlockContainer.cs

@ -1,4 +1,22 @@ @@ -1,4 +1,22 @@
using System;
// Copyright (c) 2014 Daniel Grunwald
//
// 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.Diagnostics;
using System.Linq;
@ -16,7 +34,7 @@ namespace ICSharpCode.Decompiler.IL @@ -16,7 +34,7 @@ namespace ICSharpCode.Decompiler.IL
/// </summary>
partial class BlockContainer : ILInstruction
{
public readonly IList<Block> Blocks;
public readonly InstructionCollection<Block> Blocks;
public Block EntryPoint {
get {
@ -29,19 +47,7 @@ namespace ICSharpCode.Decompiler.IL @@ -29,19 +47,7 @@ namespace ICSharpCode.Decompiler.IL
this.Blocks = new InstructionCollection<Block>(this);
}
/*
public override bool IsPeeking { get { return EntryPoint.IsPeeking; } }
public override bool NoResult { get { return true; } }
public override void TransformChildren(Func<ILInstruction, ILInstruction> transformFunc)
{
for (int i = 0; i < Blocks.Count; i++) {
if (transformFunc(Blocks[i]) != Blocks[i])
throw new InvalidOperationException("Cannot replace blocks");
}
}
*/public override void WriteTo(ITextOutput output)
public override void WriteTo(ITextOutput output)
{
output.WriteLine("BlockContainer {");
output.Indent();

59
ICSharpCode.Decompiler/IL/Instructions/Branch.cs

@ -1,4 +1,22 @@ @@ -1,4 +1,22 @@
using System;
// Copyright (c) 2014 Daniel Grunwald
//
// 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.Diagnostics;
using System.Linq;
@ -9,7 +27,8 @@ namespace ICSharpCode.Decompiler.IL @@ -9,7 +27,8 @@ namespace ICSharpCode.Decompiler.IL
{
partial class Branch : SimpleInstruction
{
public readonly int TargetILOffset;
readonly int targetILOffset;
Block targetBlock;
/// <summary>
/// Pops the specified number of arguments from the evaluation stack during the branching operation.
@ -20,18 +39,48 @@ namespace ICSharpCode.Decompiler.IL @@ -20,18 +39,48 @@ namespace ICSharpCode.Decompiler.IL
public Branch(int targetILOffset) : base(OpCode.Branch)
{
this.TargetILOffset = targetILOffset;
this.targetILOffset = targetILOffset;
}
public int TargetILOffset {
get { return targetBlock != null ? targetBlock.ILRange.Start : targetILOffset; }
}
public Block TargetBlock {
get { return targetBlock; }
set {
if (targetBlock != null && IsConnected)
targetBlock.IncomingEdgeCount--;
targetBlock = value;
if (targetBlock != null && IsConnected)
targetBlock.IncomingEdgeCount++;
}
}
protected override void Connected()
{
base.Connected();
if (targetBlock != null)
targetBlock.IncomingEdgeCount++;
}
protected override void Disconnected()
{
base.Disconnected();
if (targetBlock != null)
targetBlock.IncomingEdgeCount--;
}
public string TargetLabel {
get { return CecilExtensions.OffsetToString(TargetILOffset); }
get { return targetBlock != null ? targetBlock.Label : CecilExtensions.OffsetToString(TargetILOffset); }
}
public override void WriteTo(ITextOutput output)
{
output.Write(OpCode);
output.Write(' ');
output.WriteReference(TargetLabel, TargetILOffset, isLocal: true);
output.WriteReference(TargetLabel, (object)targetBlock ?? TargetILOffset, isLocal: true);
if (PopCount != 0) {
output.Write(" (pop ");
output.Write(PopCount.ToString());

69
ICSharpCode.Decompiler/IL/Instructions/ILFunction.cs

@ -0,0 +1,69 @@ @@ -0,0 +1,69 @@
// Copyright (c) 2014 Daniel Grunwald
//
// 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 Mono.Cecil;
using ICSharpCode.Decompiler.Disassembler;
namespace ICSharpCode.Decompiler.IL
{
partial class ILFunction
{
public readonly MethodDefinition Method;
public readonly IList<ILVariable> Variables = new List<ILVariable>();
public ILFunction(MethodDefinition method, ILInstruction body) : base(OpCode.ILFunction)
{
this.Body = body;
this.Method = method;
}
public override void WriteTo(ITextOutput output)
{
output.Write(OpCode);
output.Write(' ');
Method.WriteTo(output);
output.WriteLine(" {");
output.Indent();
foreach (var variable in Variables) {
variable.WriteDefinitionTo(output);
output.WriteLine();
}
output.WriteLine();
body.WriteTo(output);
output.Unindent();
output.WriteLine("}");
}
protected override InstructionFlags ComputeFlags()
{
// Creating a lambda may throw OutOfMemoryException
return InstructionFlags.MayThrow;
}
internal override ILInstruction Inline(InstructionFlags flagsBefore, Stack<ILInstruction> instructionStack, out bool finished)
{
// To the outside, lambda creation looks like a constant
finished = true;
return this;
}
}
}

15
ICSharpCode.Decompiler/IL/Instructions/InstructionCollection.cs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System;
using System.Collections.ObjectModel;
using System.Linq;
namespace ICSharpCode.Decompiler.IL
{
@ -61,5 +62,19 @@ namespace ICSharpCode.Decompiler.IL @@ -61,5 +62,19 @@ namespace ICSharpCode.Decompiler.IL
parentInstruction.AddChildInstruction(item);
base.SetItem(index, item);
}
public int RemoveAll(Predicate<T> predicate)
{
int removed = 0;
for (int i = 0; i < this.Count;) {
if (predicate(this[i])) {
RemoveAt(i);
removed++;
} else {
i++;
}
}
return removed;
}
}
}

20
ICSharpCode.Decompiler/IL/Instructions/MemoryInstructions.cs

@ -1,4 +1,22 @@ @@ -1,4 +1,22 @@
using ICSharpCode.Decompiler.Disassembler;
// Copyright (c) 2014 Daniel Grunwald
//
// 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 ICSharpCode.Decompiler.Disassembler;
using Mono.Cecil;
using System;
using System.Collections.Generic;

64
ICSharpCode.Decompiler/IL/TransformingVisitor.cs

@ -0,0 +1,64 @@ @@ -0,0 +1,64 @@
// Copyright (c) 2014 Daniel Grunwald
//
// 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.Diagnostics;
using Mono.Cecil;
namespace ICSharpCode.Decompiler.IL
{
/// <summary>
/// Visitor that applies a list of transformations to the IL Ast.
/// </summary>
public class TransformingVisitor : ILVisitor<ILInstruction>
{
protected override ILInstruction Default(ILInstruction inst)
{
inst.TransformChildren(this);
return inst;
}
protected internal override ILInstruction VisitBranch(Branch inst)
{
// If this branch is the only edge to the target block, we can inline the target block here:
if (inst.TargetBlock.IncomingEdgeCount == 1 && inst.PopCount == 0) {
return inst.TargetBlock;
}
return base.VisitBranch(inst);
}
protected internal override ILInstruction VisitBlockContainer(BlockContainer container)
{
container.TransformChildren(this);
// VisitBranch() 'steals' blocks from containers. Remove all blocks that were stolen from the block list:
Debug.Assert(container.EntryPoint.IncomingEdgeCount > 0);
container.Blocks.RemoveAll(b => b.IncomingEdgeCount == 0);
// If the container only contains a single block, and the block contents do not jump back to the block start,
// we can remove the container.
if (container.Blocks.Count == 1 && container.EntryPoint.IncomingEdgeCount == 1) {
// If the block has only one instruction, we can remove the block too
if (container.EntryPoint.Instructions.Count == 1)
return container.EntryPoint.Instructions[0];
return container.EntryPoint;
}
return container;
}
}
}

8
ILSpy/Languages/ILAstLanguage.cs

@ -99,10 +99,8 @@ namespace ICSharpCode.ILSpy @@ -99,10 +99,8 @@ namespace ICSharpCode.ILSpy
//}
}
public override string FileExtension
{
get
{
public override string FileExtension {
get {
return ".il";
}
}
@ -151,7 +149,7 @@ namespace ICSharpCode.ILSpy @@ -151,7 +149,7 @@ namespace ICSharpCode.ILSpy
if (!method.HasBody)
return;
ILReader reader = new ILReader(method.Body, options.CancellationToken);
reader.WriteBlocks(output, instructionInlining);
reader.CreateFunction(instructionInlining).WriteTo(output);
}
}
}

Loading…
Cancel
Save