Browse Source

Worked on ILAst instruction representation

pull/728/head
Daniel Grunwald 11 years ago
parent
commit
49ce1bcea3
  1. 23
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  2. 44
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  3. 31
      ICSharpCode.Decompiler/CSharp/StatementBuilder.cs
  4. 9
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  5. 35
      ICSharpCode.Decompiler/IL/BlockBuilder.cs
  6. 36
      ICSharpCode.Decompiler/IL/ILReader.cs
  7. 20
      ICSharpCode.Decompiler/IL/ILTypeExtensions.cs
  8. 37
      ICSharpCode.Decompiler/IL/ILVariable.cs
  9. 37
      ICSharpCode.Decompiler/IL/InstructionFlags.cs
  10. 20
      ICSharpCode.Decompiler/IL/InstructionOutputExtensions.cs
  11. 646
      ICSharpCode.Decompiler/IL/Instructions.cs
  12. 230
      ICSharpCode.Decompiler/IL/Instructions.tt
  13. 56
      ICSharpCode.Decompiler/IL/Instructions/BinaryComparisonInstruction.cs
  14. 133
      ICSharpCode.Decompiler/IL/Instructions/BinaryInstruction.cs
  15. 84
      ICSharpCode.Decompiler/IL/Instructions/BinaryNumericInstruction.cs
  16. 18
      ICSharpCode.Decompiler/IL/Instructions/Block.cs
  17. 143
      ICSharpCode.Decompiler/IL/Instructions/CallInstruction.cs
  18. 57
      ICSharpCode.Decompiler/IL/Instructions/Conv.cs
  19. 73
      ICSharpCode.Decompiler/IL/Instructions/ILInstruction.cs
  20. 58
      ICSharpCode.Decompiler/IL/Instructions/Return.cs
  21. 38
      ICSharpCode.Decompiler/IL/Instructions/SimpleInstruction.cs
  22. 60
      ICSharpCode.Decompiler/IL/Instructions/UnaryInstruction.cs
  23. 22
      ICSharpCode.Decompiler/IL/PrimitiveType.cs
  24. 20
      ICSharpCode.Decompiler/IL/SemanticHelper.cs
  25. 20
      ICSharpCode.Decompiler/IL/StackType.cs
  26. 40
      ICSharpCode.Decompiler/IL/Visitors/CountPopInstructionsVisitor.cs
  27. 9
      ICSharpCode.Decompiler/Util/Interval.cs

23
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -1,4 +1,22 @@ @@ -1,4 +1,22 @@
using ICSharpCode.Decompiler.IL;
// 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.IL;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.CSharp.Refactoring;
using ICSharpCode.NRefactory.TypeSystem;
@ -54,7 +72,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -54,7 +72,8 @@ namespace ICSharpCode.Decompiler.CSharp
{
var unresolved = member.UnresolvedMember;
lock (entityDict) {
if (unresolved != null && entityDict.TryGetValue(unresolved, out var mr))
MemberReference mr;
if (unresolved != null && entityDict.TryGetValue(unresolved, out mr))
return mr;
}
return null;

44
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -1,4 +1,22 @@ @@ -1,4 +1,22 @@
using ICSharpCode.Decompiler.IL;
// 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.IL;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.TypeSystem;
using System;
@ -12,13 +30,25 @@ namespace ICSharpCode.Decompiler.CSharp @@ -12,13 +30,25 @@ namespace ICSharpCode.Decompiler.CSharp
/// <summary>
/// Translates from ILAst to C# expressions.
/// </summary>
class ExpressionBuilder(ICompilation compilation) : ILVisitor<ExpressionBuilder.ConvertedExpression>
class ExpressionBuilder : ILVisitor<ExpressionBuilder.ConvertedExpression>
{
private readonly ICompilation compilation = compilation;
internal struct ConvertedExpression(Expression expression, IType type) {
public readonly Expression Expression = expression;
public readonly IType Type = type;
private readonly ICompilation compilation;
public ExpressionBuilder(ICompilation compilation)
{
this.compilation = compilation;
}
internal struct ConvertedExpression
{
public readonly Expression Expression;
public readonly IType Type;
public ConvertedExpression(Expression expression, IType type)
{
this.Expression = expression;
this.Type = type;
}
}
public Expression Convert(ILInstruction inst)

31
ICSharpCode.Decompiler/CSharp/StatementBuilder.cs

@ -1,4 +1,22 @@ @@ -1,4 +1,22 @@
using ICSharpCode.Decompiler.IL;
// 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.IL;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.TypeSystem;
using System;
@ -9,10 +27,15 @@ using System.Threading.Tasks; @@ -9,10 +27,15 @@ using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.CSharp
{
class StatementBuilder(ICompilation compilation) : ILVisitor<Statement>
class StatementBuilder : ILVisitor<Statement>
{
readonly ExpressionBuilder exprBuilder = new ExpressionBuilder(compilation);
readonly ExpressionBuilder exprBuilder;
public StatementBuilder(ICompilation compilation)
{
this.exprBuilder = new ExpressionBuilder(compilation);
}
public Statement Convert(ILInstruction inst)
{
return inst.AcceptVisitor(this);

9
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -19,7 +19,6 @@ @@ -19,7 +19,6 @@
<AssemblyOriginatorKeyFile>..\NRefactory\ICSharpCode.NRefactory.snk</AssemblyOriginatorKeyFile>
<DelaySign>False</DelaySign>
<AssemblyOriginatorKeyMode>File</AssemblyOriginatorKeyMode>
<LangVersion>experimental</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Platform)' == 'AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
@ -72,12 +71,17 @@ @@ -72,12 +71,17 @@
<DesignTime>True</DesignTime>
<DependentUpon>Instructions.tt</DependentUpon>
</Compile>
<Compile Include="IL\Instructions\BinaryComparisonInstruction.cs" />
<Compile Include="IL\Instructions\BinaryInstruction.cs" />
<Compile Include="IL\Instructions\BinaryNumericInstruction.cs" />
<Compile Include="IL\Instructions\Block.cs" />
<Compile Include="IL\Instructions\CallInstruction.cs" />
<Compile Include="IL\Instructions\Conv.cs" />
<Compile Include="IL\Instructions\ILInstruction.cs" />
<Compile Include="IL\Instructions\Return.cs" />
<Compile Include="IL\Instructions\SimpleInstruction.cs" />
<Compile Include="IL\Instructions\UnaryInstruction.cs" />
<Compile Include="IL\Visitors\CountPopInstructionsVisitor.cs" />
<Compile Include="TypesHierarchyHelpers.cs" />
<Compile Include="CecilExtensions.cs" />
<Compile Include="Disassembler\DisassemblerHelpers.cs" />
@ -138,6 +142,9 @@ @@ -138,6 +142,9 @@
<ItemGroup>
<Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" />
</ItemGroup>
<ItemGroup>
<Folder Include="IL\Visitors" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
<Target Name="BeforeBuild">
<MSBuild Projects="$(MSBuildProjectDirectory)\..\BuildTools\UpdateAssemblyInfo\UpdateAssemblyInfo.csproj" Targets="Build" Properties="Configuration=Debug" />

35
ICSharpCode.Decompiler/IL/BlockBuilder.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;
using System.Collections.Generic;
using System.Diagnostics;
@ -8,12 +26,18 @@ using System.Threading.Tasks; @@ -8,12 +26,18 @@ using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.IL
{
class BlockBuilder(Mono.Cecil.Cil.MethodBody body, bool instructionInlining)
class BlockBuilder
{
readonly Stack<ILInstruction> instructionStack;
public BlockBuilder(Mono.Cecil.Cil.MethodBody body, bool instructionInlining)
{
this.instructionStack = (instructionInlining ? new Stack<ILInstruction>() : null);
}
BlockContainer currentContainer;
Block currentBlock;
Stack<ILInstruction> instructionStack = (instructionInlining ? new Stack<ILInstruction>() : null);
public BlockContainer CreateBlocks(List<ILInstruction> instructions, BitArray incomingBranches)
{
currentContainer = new BlockContainer();
@ -35,7 +59,8 @@ namespace ICSharpCode.Decompiler.IL @@ -35,7 +59,8 @@ namespace ICSharpCode.Decompiler.IL
// inlining disabled
currentBlock.Instructions.Add(inst);
} else {
var inlinedInst = inst.Inline(InstructionFlags.None, instructionStack, out bool finished);
bool finished;
var inlinedInst = inst.Inline(InstructionFlags.None, instructionStack, out finished);
if (inlinedInst is Branch) {
// Values currently on the stack might be used on both sides of the branch,
// so we can't inline them.

36
ICSharpCode.Decompiler/IL/ILReader.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.Linq;
using System.Text;
@ -11,11 +29,19 @@ using System.Threading; @@ -11,11 +29,19 @@ using System.Threading;
namespace ICSharpCode.Decompiler.IL
{
public class ILReader(Mono.Cecil.Cil.MethodBody body, CancellationToken cancellationToken)
public class ILReader
{
private readonly Mono.Cecil.Cil.MethodBody body = body;
private readonly CancellationToken cancellationToken = cancellationToken;
private readonly Mono.Cecil.Cil.MethodBody body;
private readonly CancellationToken cancellationToken;
public ILReader(Mono.Cecil.Cil.MethodBody body, CancellationToken cancellationToken)
{
if (body == null)
throw new ArgumentNullException("body");
this.body = body;
this.cancellationToken = cancellationToken;
}
internal static ILOpCode ReadOpCode(ref BlobReader reader)
{
byte b = reader.ReadByte();
@ -699,7 +725,7 @@ namespace ICSharpCode.Decompiler.IL @@ -699,7 +725,7 @@ namespace ICSharpCode.Decompiler.IL
{
var method = (MethodReference)ReadAndDecodeMetadataToken();
var inst = new CallInstruction(opCode, method);
for (int i = 0; i < inst.Operands.Length; i++) {
for (int i = 0; i < inst.Arguments.Length; i++) {
stack.Pop();
}
var returnType = (opCode == OpCode.NewObj ? method.DeclaringType : method.ReturnType).GetStackType();

20
ICSharpCode.Decompiler/IL/ILTypeExtensions.cs

@ -1,4 +1,22 @@ @@ -1,4 +1,22 @@
using Mono.Cecil;
// 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 Mono.Cecil;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;

37
ICSharpCode.Decompiler/IL/ILVariable.cs

@ -1,4 +1,22 @@ @@ -1,4 +1,22 @@
using Mono.Cecil;
// 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 Mono.Cecil;
using Mono.Cecil.Cil;
using System;
using System.Collections.Generic;
@ -14,14 +32,23 @@ namespace ICSharpCode.Decompiler.IL @@ -14,14 +32,23 @@ namespace ICSharpCode.Decompiler.IL
Parameter,
}
class ILVariable(VariableKind kind, TypeReference type, int index)
class ILVariable
{
public readonly VariableKind Kind = kind;
public readonly TypeReference Type = type;
public readonly int Index = index;
public readonly VariableKind Kind;
public readonly TypeReference Type;
public readonly int Index;
readonly object CecilObject;
public ILVariable(VariableKind kind, TypeReference type, int index)
{
if (type == null)
throw new ArgumentNullException("type");
this.Kind = kind;
this.Type = type;
this.Index = index;
}
public ILVariable(VariableDefinition v)
: this(VariableKind.Local, v.VariableType, v.Index)
{

37
ICSharpCode.Decompiler/IL/InstructionFlags.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.Linq;
using System.Text;
@ -10,6 +28,9 @@ namespace ICSharpCode.Decompiler.IL @@ -10,6 +28,9 @@ namespace ICSharpCode.Decompiler.IL
public enum InstructionFlags
{
None = 0,
/// <summary>
/// The instruction may pop from the evaluation stack.
/// </summary>
MayPop = 0x01,
MayPeek = 0x02,
/// <summary>
@ -17,19 +38,19 @@ namespace ICSharpCode.Decompiler.IL @@ -17,19 +38,19 @@ namespace ICSharpCode.Decompiler.IL
/// </summary>
MayThrow = 0x04,
/// <summary>
/// The instruction may read from local variables.
/// The instruction may exit with a branch or return.
/// </summary>
MayReadLocals = 0x08,
MayBranch = 0x08,
/// <summary>
/// The instruction may write to local variables.
/// The instruction may read from local variables.
/// </summary>
MayWriteLocals = 0x10,
MayReadLocals = 0x10,
/// <summary>
/// The instruction may exit with a jump or return.
/// The instruction may write to local variables.
/// </summary>
MayJump = 0x20,
MayWriteLocals = 0x20,
/// <summary>
/// The instruction may have side effects, such as writing to heap memory,
/// The instruction may have side effects, such as accessing heap memory,
/// performing system calls, writing to local variables through pointers, etc.
/// </summary>
SideEffects = 0x40,

20
ICSharpCode.Decompiler/IL/InstructionOutputExtensions.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.Linq;
using System.Text;

646
ICSharpCode.Decompiler/IL/Instructions.cs

File diff suppressed because it is too large Load Diff

230
ICSharpCode.Decompiler/IL/Instructions.tt

@ -1,4 +1,22 @@ @@ -1,4 +1,22 @@
<#@ template debug="false" hostspecific="false" language="C#" #>
// 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.
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
@ -6,61 +24,97 @@ @@ -6,61 +24,97 @@
<#@ output extension=".cs" #>
<#
OpCode[] opCodes = {
new OpCode("Nop", "No operation. Takes 0 arguments and returns void.", VoidResult, NoArguments),
new OpCode("Pop", "Pops the top of the evaluation stack and returns the value.", NoArguments, NonVoidResult),
new OpCode("Peek", "Peeks at the top of the evaluation stack and returns the value. Corresponds to IL 'dup'.", Peeking, NoArguments, NonVoidResult),
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("Nop", "No operation. Takes 0 arguments and returns void.",
VoidResult, NoArguments),
new OpCode("Pop", "Pops the top of the evaluation stack and returns the value.",
NoArguments, ResultTypeParam),
new OpCode("Peek", "Peeks at the top of the evaluation stack and returns the value. Corresponds to IL 'dup'.",
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("BlockContainer", "A container of IL blocks.", VoidResult),
new OpCode("Block", "A block of IL instructions."),
new OpCode("LogicNot", "Unary operator that expects an input of type I4. Returns 1 (of type I4) if the input value is 0. Otherwise, returns 0 (of type I4).", I4Result, Unary),
new OpCode("LogicNot", "Unary operator that expects an input of type I4. Returns 1 (of type I4) if the input value is 0. Otherwise, returns 0 (of type I4).",
ResultType("I4"), Unary),
new OpCode("Add", "Adds two numbers.", BinaryNumeric),
new OpCode("Sub", "Subtracts two numbers", BinaryNumeric),
new OpCode("Mul", "Multiplies two numbers", BinaryNumeric),
new OpCode("Div", "Divides two numbers", BinaryNumeric, MayThrow),
new OpCode("Rem", "Division remainder", BinaryNumeric, MayThrow),
new OpCode("Neg", "Unary negation", Unary, NonVoidResult),
new OpCode("Neg", "Unary negation", Unary, ResultTypeParam),
new OpCode("BitAnd", "Bitwise AND", BinaryNumeric),
new OpCode("BitOr", "Bitwise OR", BinaryNumeric),
new OpCode("BitXor", "Bitwise XOR", BinaryNumeric),
new OpCode("BitNot", "Bitwise NOT", Unary, NonVoidResult),
new OpCode("Arglist", "Retrieves the RuntimeArgumentHandle.", NoArguments, NonVoidResult),
new OpCode("ConditionalBranch", "<c>if (condition) goto target;</c>.", Unary, MayBranch, HasBranchTarget, VoidResult),
new OpCode("Branch", "<c>goto target;</c>.", NoArguments, UnconditionalBranch, MayBranch, HasBranchTarget),
new OpCode("DebugBreak", "Breakpoint instruction", NoArguments, VoidResult, SideEffect),
new OpCode("Ceq", "Compare equal. Returns 1 (of type I4) if two numbers or object references are equal; 0 otherwise.", BinaryComparison),
new OpCode("Cgt", "Compare greater than. For integers, perform a signed comparison. For floating-point numbers, return 0 for unordered numbers.", BinaryComparison),
new OpCode("Cgt_Un", "Compare greater than (unordered/unsigned). For integers, perform a signed comparison. For floating-point numbers, return 1 for unordered numbers.", BinaryComparison),
new OpCode("Clt", "Compare less than. For integers, perform a signed comparison. For floating-point numbers, return 0 for unordered numbers.", BinaryComparison),
new OpCode("Clt_Un", "Compare less than (unordered/unsigned). For integers, perform a signed comparison. For floating-point numbers, return 1 for unordered numbers.", BinaryComparison),
new OpCode("BitNot", "Bitwise NOT", Unary, ResultTypeParam),
new OpCode("Arglist", "Retrieves the RuntimeArgumentHandle.", NoArguments, ResultType("O")),
new OpCode("ConditionalBranch", "<c>if (condition) goto target;</c>.",
Unary, MayBranch, HasBranchTarget, VoidResult),
new OpCode("Branch", "<c>goto target;</c>.",
NoArguments, UnconditionalBranch, MayBranch, HasBranchTarget),
new OpCode("DebugBreak", "Breakpoint instruction",
NoArguments, VoidResult, SideEffect),
new OpCode("Ceq", "Compare equal. Returns 1 (of type I4) if two numbers or object references are equal; 0 otherwise.",
BinaryComparison),
new OpCode("Cgt", "Compare greater than. For integers, perform a signed comparison. For floating-point numbers, return 0 for unordered numbers.",
BinaryComparison),
new OpCode("Cgt_Un", "Compare greater than (unordered/unsigned). For integers, perform a signed comparison. For floating-point numbers, return 1 for unordered numbers.",
BinaryComparison),
new OpCode("Clt", "Compare less than. For integers, perform a signed comparison. For floating-point numbers, return 0 for unordered numbers.",
BinaryComparison),
new OpCode("Clt_Un", "Compare less than (unordered/unsigned). For integers, perform a signed comparison. For floating-point numbers, return 1 for unordered numbers.",
BinaryComparison),
new OpCode("Call", "Non-virtual method call.", Call),
new OpCode("CallVirt", "Virtual method call.", Call),
new OpCode("CkFinite", "Checks that the float on top of the stack is not NaN or infinite.", Peeking, NoArguments, MayThrow, VoidResult),
new OpCode("Conv", "Numeric cast.", Unary, NonVoidResult),
new OpCode("Ldloc", "Loads the value of a local variable. (ldarg/ldloc)", NoArguments, NonVoidResult, HasVariableOperand),
new OpCode("Ldloca", "Loads the address of a local variable. (ldarga/ldloca)", NoArguments, RefResult, HasVariableOperand),
new OpCode("Stloc", "Stores a value into a local variable. (starg/stloc)", Unary, VoidResult, HasVariableOperand),
new OpCode("LdStr", "Loads a constant string.", LoadConstant),
new OpCode("LdcI4", "Loads a constant 32-bit integer.", LoadConstant, I4Result),
new OpCode("LdcI8", "Loads a constant 64-bit integer.", LoadConstant, NonVoidResult),
new OpCode("LdcF", "Loads a constant floating-point number.", LoadConstant),
new OpCode("LdNull", "Loads the null reference.", LoadConstant),
new OpCode("Return", "Returns from the current method or lambda.", MayBranch, UnconditionalBranch),
new OpCode("CkFinite", "Checks that the float on top of the stack is not NaN or infinite.",
Peeking, NoArguments, MayThrow, VoidResult),
new OpCode("Conv", "Numeric cast.",
Unary, CustomConstructor),
new OpCode("LdLoc", "Loads the value of a local variable. (ldarg/ldloc)",
NoArguments, HasVariableOperand, ResultType("Variable.Type.ToStackType()")),
new OpCode("LdLoca", "Loads the address of a local variable. (ldarga/ldloca)",
NoArguments, ResultType("Ref"), HasVariableOperand),
new OpCode("StLoc", "Stores a value into a local variable. (starg/stloc)",
Unary, VoidResult, HasVariableOperand),
new OpCode("LdStr", "Loads a constant string.",
LoadConstant, ResultType("O")),
new OpCode("LdcI4", "Loads a constant 32-bit integer.",
LoadConstant, ResultType("I4")),
new OpCode("LdcI8", "Loads a constant 64-bit integer.",
LoadConstant, ResultType("I8")),
new OpCode("LdcF", "Loads a constant floating-point number.",
LoadConstant, ResultType("F")),
new OpCode("LdNull", "Loads the null reference.",
LoadConstant, ResultType("O")),
new OpCode("Return", "Returns from the current method or lambda.",
MayBranch, UnconditionalBranch),
new OpCode("Shl", "Shift left", BinaryNumeric),
new OpCode("Shr", "Shift right", BinaryNumeric),
new OpCode("Ldfld", "Load instance field", Unary, MayThrow, SideEffect, NonVoidResult, HasFieldOperand),
new OpCode("Ldflda", "Load address of instance field", Unary, MayThrow, RefResult, HasFieldOperand),
new OpCode("Stfld", "Store value to instance field", Binary, SideEffect, MayThrow, VoidResult, HasFieldOperand),
new OpCode("Ldsfld", "Load static field", NoArguments, SideEffect, NonVoidResult, HasFieldOperand),
new OpCode("Ldsflda", "Load static field address", NoArguments, RefResult, HasFieldOperand),
new OpCode("Stsfld", "Store value to static field", Unary, SideEffect, VoidResult, HasFieldOperand),
new OpCode("IsInst", "Test if object is instance of class or interface.", Unary, NonVoidResult, HasTypeOperand),
new OpCode("LdInd", "Indirect load (ref/pointer dereference).", Unary, NonVoidResult, HasTypeOperand, SideEffect, MayThrow),
new OpCode("UnboxAny", "Unbox a value.", Unary, NonVoidResult, HasTypeOperand, SideEffect, MayThrow),
new OpCode("NewObj", "Creates an object instance and calls the constructor.", Call),
new OpCode("Throw", "Throws an exception.", Unary, MayThrow, UnconditionalBranch),
new OpCode("LdLen", "Returns the length of an array as 'native unsigned int'.", Unary, MayThrow, NonVoidResult),
new OpCode("Ldfld", "Load instance field",
Unary, MayThrow, SideEffect, HasFieldOperand),
new OpCode("Ldflda", "Load address of instance field",
Unary, MayThrow, HasFieldOperand, ResultType("Ref")),
new OpCode("Stfld", "Store value to instance field",
Binary, SideEffect, MayThrow, VoidResult, HasFieldOperand),
new OpCode("Ldsfld", "Load static field",
NoArguments, SideEffect, HasFieldOperand),
new OpCode("Ldsflda", "Load static field address",
NoArguments, ResultType("Ref"), HasFieldOperand),
new OpCode("Stsfld", "Store value to static field",
Unary, SideEffect, VoidResult, HasFieldOperand),
new OpCode("IsInst", "Test if object is instance of class or interface.",
Unary, HasTypeOperand, ResultType("O")),
new OpCode("LdInd", "Indirect load (ref/pointer dereference).",
Unary, HasTypeOperand, SideEffect, MayThrow),
new OpCode("UnboxAny", "Unbox a value.",
Unary, HasTypeOperand, SideEffect, MayThrow),
new OpCode("NewObj", "Creates an object instance and calls the constructor.",
Call, ResultType("O")),
new OpCode("Throw", "Throws an exception.",
Unary, MayThrow, UnconditionalBranch),
new OpCode("LdLen", "Returns the length of an array as 'native unsigned int'.",
Unary, MayThrow, ResultType("I")),
};
@ -83,10 +137,20 @@ namespace ICSharpCode.Decompiler.IL @@ -83,10 +137,20 @@ namespace ICSharpCode.Decompiler.IL
<# foreach (OpCode opCode in opCodes) { #>
/// <summary><#=opCode.Description#></summary>
public sealed partial class <#=opCode.Name#>(<#=string.Join(", ", opCode.ConstructorParameters)#>) : <#=opCode.BaseClass#>(<#=string.Join(", ", opCode.BaseConstructorArguments)#>)
public sealed partial class <#=opCode.Name#> : <#=opCode.BaseClass#>
{
<#=string.Join(Environment.NewLine, opCode.Members)#>
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
<# if (opCode.GenerateConstructor) { #>
public <#=opCode.Name#>(<#=string.Join(", ", opCode.ConstructorParameters)#>) : base(<#=string.Join(", ", opCode.BaseConstructorArguments)#>)
{<#=Body(opCode.ConstructorBody)#>}
<# } #>
<# if (opCode.Flags.Count > 1) { #>
protected override InstructionFlags ComputeFlags()
{
return <#=string.Join(" | ", opCode.Flags)#>;
}
<# } #>
<#=string.Join(Environment.NewLine, opCode.Members.Select(m => "\t\t" + m))#>
public sealed override T AcceptVisitor<T>(ILVisitor<T> visitor)
{
return visitor.Visit<#=opCode.Name#>(this);
}
@ -95,12 +159,12 @@ namespace ICSharpCode.Decompiler.IL @@ -95,12 +159,12 @@ namespace ICSharpCode.Decompiler.IL
<# } #>
public abstract class ILVisitor<TReturn>
public abstract class ILVisitor<T>
{
protected abstract TReturn Default(ILInstruction inst);
protected abstract T Default(ILInstruction inst);
<# foreach (OpCode opCode in opCodes) { #>
protected internal virtual TReturn Visit<#=opCode.Name#>(<#=opCode.Name#> inst)
protected internal virtual T Visit<#=opCode.Name#>(<#=opCode.Name#> inst)
{
return Default(inst);
}
@ -109,6 +173,19 @@ namespace ICSharpCode.Decompiler.IL @@ -109,6 +173,19 @@ namespace ICSharpCode.Decompiler.IL
}
<#+
static string Body(List<string> statements)
{
StringBuilder b = new StringBuilder();
foreach (var st in statements) {
b.AppendLine();
b.Append("\t\t\t");
b.Append(st);
}
b.AppendLine();
b.Append("\t\t");
return b.ToString();
}
class OpCode {
public readonly string Name;
public readonly string Description;
@ -122,39 +199,65 @@ namespace ICSharpCode.Decompiler.IL @@ -122,39 +199,65 @@ namespace ICSharpCode.Decompiler.IL
trait(this);
}
public bool GenerateConstructor = true;
public List<string> ConstructorParameters = new List<string>();
public List<string> ConstructorBody = new List<string>();
public string BaseClass = "ILInstruction";
public List<string> BaseConstructorArguments = new List<string>();
public List<string> Members = new List<string>();
public List<string> Flags = new List<string>() { "base.ComputeFlags()" };
}
static Action<OpCode> CustomConstructor = opCode => {
opCode.GenerateConstructor = false;
};
static Action<OpCode> HasFlag(string name)
{
return opCode => {
opCode.Flags.Add(name);
};
}
// Peeking trait: the instruction looks at the top-of-stack without popping
static Action<OpCode> Peeking = opCode => { };
static Action<OpCode> Peeking = HasFlag("InstructionFlags.MayPeek");
// ResultType trait: the instruction has the specified result type.
static Action<OpCode> ResultType(string type)
{
if (!type.Contains("."))
type = "StackType." + type;
return opCode => {
opCode.Members.Add("public override StackType ResultType { get { return " + type + "; } }");
};
}
// VoidResult trait: the instruction has no result and is not usable as an argument
static Action<OpCode> VoidResult = opCode => { };
// NonVoidResult trait: the instruction has a result and is usable as an argument
static Action<OpCode> NonVoidResult = opCode => { };
static Action<OpCode> VoidResult = ResultType("Void");
// I4Result trait: the instruction results in StackType.I4. Implies NonVoidResult.
static Action<OpCode> I4Result = NonVoidResult;
// RefResult trait: the instruction results in StackType.Ref. Implies NonVoidResult.
static Action<OpCode> RefResult = NonVoidResult;
// ResultTypeParam trait: the instruction takes its result type as ctor parameter
static Action<OpCode> ResultTypeParam = opCode => {
opCode.ConstructorParameters.Add("StackType resultType");
opCode.ConstructorBody.Add("this.resultType = resultType;");
opCode.Members.Add("StackType resultType;");
opCode.Members.Add("public override StackType ResultType { get { return resultType; } }");
};
// MayThrow trait: the instruction may throw exceptions
static Action<OpCode> MayThrow = opCode => {};
static Action<OpCode> MayThrow = HasFlag("InstructionFlags.MayThrow");
// MayBranch trait: the instruction may cause control flow to branch (e.g. branch, conditionalbranch, return)
static Action<OpCode> MayBranch = opCode => {};
static Action<OpCode> MayBranch = HasFlag("InstructionFlags.MayBranch");
// HasBranchTarget trait: the instruction has an explicit branch target offset
static Action<OpCode> HasBranchTarget = opCode => {};
// UnconditionalBranch trait: the instruction does not produce a result normally; it always branches or throws an exception. Implies VoidResult.
static Action<OpCode> UnconditionalBranch = opCode => {};
static Action<OpCode> UnconditionalBranch = opCode => {
VoidResult(opCode);
};
// NoArguments trait: the instruction no arguments
static Action<OpCode> NoArguments = opCode => {
@ -175,8 +278,10 @@ namespace ICSharpCode.Decompiler.IL @@ -175,8 +278,10 @@ namespace ICSharpCode.Decompiler.IL
static Action<OpCode> BinaryNumeric = opCode => {
opCode.BaseClass = "BinaryNumericInstruction";
opCode.ConstructorParameters.Add("StackType opType");
opCode.ConstructorParameters.Add("StackType resultType");
opCode.ConstructorParameters.Add("OverflowMode overflowMode");
opCode.BaseConstructorArguments.Add("opType");
opCode.BaseConstructorArguments.Add("resultType");
opCode.BaseConstructorArguments.Add("overflowMode");
};
@ -188,7 +293,7 @@ namespace ICSharpCode.Decompiler.IL @@ -188,7 +293,7 @@ namespace ICSharpCode.Decompiler.IL
};
// SideEffect trait: the instruction has a non-local side effect
static Action<OpCode> SideEffect = opCode => {};
static Action<OpCode> SideEffect = HasFlag("InstructionFlags.SideEffect");
// Call trait: the instruction performs a method call
static Action<OpCode> Call = opCode => {
@ -204,9 +309,8 @@ namespace ICSharpCode.Decompiler.IL @@ -204,9 +309,8 @@ namespace ICSharpCode.Decompiler.IL
static Action<OpCode> HasTypeOperand = opCode => {};
// LoadConstant trait: the instruction loads a compile-time constant. Implies NoArguments and NonVoidResult
// LoadConstant trait: the instruction loads a compile-time constant. Implies NoArguments.
static Action<OpCode> LoadConstant = opCode => {
NoArguments(opCode);
NonVoidResult(opCode);
};
#>

56
ICSharpCode.Decompiler/IL/Instructions/BinaryComparisonInstruction.cs

@ -0,0 +1,56 @@ @@ -0,0 +1,56 @@
// 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;
using System.Text;
using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.IL
{
public abstract class BinaryComparisonInstruction : BinaryInstruction
{
public readonly StackType OpType;
protected BinaryComparisonInstruction(OpCode opCode, StackType opType) : base(opCode)
{
this.OpType = opType;
}
public sealed override StackType ResultType {
get {
return StackType.I4;
}
}
public override void WriteTo(ITextOutput output)
{
output.Write(OpCode);
output.Write('.');
output.Write(OpType);
output.Write('(');
Left.WriteTo(output);
output.Write(", ");
Right.WriteTo(output);
output.Write(')');
}
}
}

133
ICSharpCode.Decompiler/IL/Instructions/BinaryInstruction.cs

@ -1,16 +1,89 @@ @@ -1,16 +1,89 @@
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;
using System.Text;
using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.IL
{
public abstract class BinaryInstruction(OpCode opCode) : ILInstruction(opCode)
public abstract class BinaryInstruction : ILInstruction
{
public ILInstruction Left = Pop;
public ILInstruction Right = Pop;
ILInstruction left = Pop;
ILInstruction right = Pop;
protected BinaryInstruction(OpCode opCode) : base(opCode)
{
}
public ILInstruction Left {
get { return left; }
set {
Debug.Assert(value.ResultType != StackType.Void);
left = value;
InvalidateFlags();
}
}
public ILInstruction Right {
get { return right; }
set {
Debug.Assert(value.ResultType != StackType.Void);
right = value;
InvalidateFlags();
}
}
internal override void CheckInvariant()
{
base.CheckInvariant();
Left.CheckInvariant();
Right.CheckInvariant();
Debug.Assert(Left.ResultType != StackType.Void);
Debug.Assert(Right.ResultType != StackType.Void);
}
public override void WriteTo(ITextOutput output)
{
output.Write(OpCode);
output.Write('(');
Left.WriteTo(output);
output.Write(", ");
Right.WriteTo(output);
output.Write(')');
}
protected override InstructionFlags ComputeFlags()
{
return Left.Flags | Right.Flags;
}
public sealed override TAccumulate AggregateChildren<TSource, TAccumulate>(TAccumulate initial, ILVisitor<TSource> visitor, Func<TAccumulate, TSource, TAccumulate> func)
{
TAccumulate value = initial;
value = func(value, Left.AcceptVisitor(visitor));
value = func(value, Right.AcceptVisitor(visitor));
return value;
}
/*
public override bool IsPeeking { get { return Left.IsPeeking; } }
@ -29,54 +102,4 @@ namespace ICSharpCode.Decompiler.IL @@ -29,54 +102,4 @@ namespace ICSharpCode.Decompiler.IL
return this;
}*/
}
public abstract class BinaryNumericInstruction(OpCode opCode, StackType opType, OverflowMode overflowMode)
: BinaryInstruction(opCode)
{
public readonly StackType OpType = opType;
public readonly OverflowMode OverflowMode = overflowMode;
public override void WriteTo(ITextOutput output)
{
output.Write(OpCode);
output.WriteSuffix(OverflowMode);
output.Write(' ');
output.Write(OpType);
output.Write('(');
Left.WriteTo(output);
output.Write(", ");
Right.WriteTo(output);
output.Write(')');
}
}
public abstract class BinaryComparisonInstruction(OpCode opCode, StackType opType)
: BinaryInstruction(opCode)
{
public readonly StackType OpType = opType;
public override void WriteTo(ITextOutput output)
{
output.Write(OpCode);
output.Write('.');
output.Write(OpType);
output.Write('(');
Left.WriteTo(output);
output.Write(", ");
Right.WriteTo(output);
output.Write(')');
}
}
public enum OverflowMode : byte
{
/// <summary>Don't check for overflow, treat integers as signed.</summary>
None = 0,
/// <summary>Check for overflow, treat integers as signed.</summary>
Ovf = 1,
/// <summary>Don't check for overflow, treat integers as unsigned.</summary>
Un = 2,
/// <summary>Check for overflow, treat integers as unsigned.</summary>
Ovf_Un = 3
}
}

84
ICSharpCode.Decompiler/IL/Instructions/BinaryNumericInstruction.cs

@ -0,0 +1,84 @@ @@ -0,0 +1,84 @@
// 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;
using System.Text;
using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.IL
{
[Flags]
public enum OverflowMode : byte
{
/// <summary>Don't check for overflow, treat integers as signed.</summary>
None = 0,
/// <summary>Check for overflow, treat integers as signed.</summary>
Ovf = 1,
/// <summary>Don't check for overflow, treat integers as unsigned.</summary>
Un = 2,
/// <summary>Check for overflow, treat integers as unsigned.</summary>
Ovf_Un = 3
}
public abstract class BinaryNumericInstruction : BinaryInstruction
{
public readonly StackType OpType;
public readonly OverflowMode OverflowMode;
readonly StackType resultType;
protected BinaryNumericInstruction(OpCode opCode, StackType opType, StackType resultType, OverflowMode overflowMode) : base(opCode)
{
this.OpType = opType;
this.resultType = resultType;
this.OverflowMode = overflowMode;
}
public sealed override StackType ResultType {
get {
return resultType;
}
}
protected override InstructionFlags ComputeFlags()
{
var flags = base.ComputeFlags();
if ((OverflowMode & OverflowMode.Ovf) != 0)
flags |= InstructionFlags.MayThrow;
return flags;
}
public override void WriteTo(ITextOutput output)
{
output.Write(OpCode);
output.WriteSuffix(OverflowMode);
output.Write(' ');
output.Write(OpType);
output.Write('(');
Left.WriteTo(output);
output.Write(", ");
Right.WriteTo(output);
output.Write(')');
}
}
}

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

@ -47,6 +47,15 @@ namespace ICSharpCode.Decompiler.IL @@ -47,6 +47,15 @@ namespace ICSharpCode.Decompiler.IL
output.WriteLine("}");
}
public override TAccumulate AggregateChildren<TSource, TAccumulate>(TAccumulate initial, ILVisitor<TSource> visitor, Func<TAccumulate, TSource, TAccumulate> func)
{
TAccumulate value = initial;
foreach (var inst in Instructions) {
value = func(value, inst.AcceptVisitor(visitor));
}
return value;
}
/*
public override InstructionFlags Flags
{
@ -107,6 +116,15 @@ namespace ICSharpCode.Decompiler.IL @@ -107,6 +116,15 @@ namespace ICSharpCode.Decompiler.IL
output.WriteLine("}");
}
public override TAccumulate AggregateChildren<TSource, TAccumulate>(TAccumulate initial, ILVisitor<TSource> visitor, Func<TAccumulate, TSource, TAccumulate> func)
{
TAccumulate value = initial;
foreach (var block in Blocks) {
value = func(value, block.AcceptVisitor(visitor));
}
return value;
}
/*
public override InstructionFlags Flags
{

143
ICSharpCode.Decompiler/IL/Instructions/CallInstruction.cs

@ -1,30 +1,143 @@ @@ -1,30 +1,143 @@
using ICSharpCode.Decompiler.Disassembler;
using Mono.Cecil;
// 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;
using System.Text;
using System.Threading.Tasks;
using Mono.Cecil;
using ICSharpCode.Decompiler.Disassembler;
namespace ICSharpCode.Decompiler.IL
{
public abstract class CallInstruction(OpCode opCode, MethodReference methodReference) : ILInstruction(opCode)
public abstract class CallInstruction : ILInstruction
{
public readonly MethodReference Method = methodReference;
public readonly ILInstruction[] Operands = InitOperands(opCode, methodReference);
static ILInstruction[] InitOperands(OpCode opCode, MethodReference mr)
public struct ArgumentCollection : IReadOnlyList<ILInstruction>
{
readonly CallInstruction inst;
public ArgumentCollection(CallInstruction inst)
{
this.inst = inst;
}
public int Count {
get { return inst.arguments.Length; }
}
public ILInstruction this[int index] {
get { return inst.arguments[index]; }
set {
Debug.Assert(value.ResultType != StackType.Void);
inst.arguments[index] = value;
inst.InvalidateFlags();
}
}
public ArgumentEnumerator GetEnumerator()
{
return new ArgumentEnumerator(inst.arguments);
}
IEnumerator<ILInstruction> IEnumerable<ILInstruction>.GetEnumerator()
{
IEnumerable<ILInstruction> arguments = inst.arguments;
return arguments.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return inst.arguments.GetEnumerator();
}
}
public struct ArgumentEnumerator
{
int popCount = mr.Parameters.Count;
if (opCode != OpCode.NewObj && mr.HasThis)
readonly ILInstruction[] arguments;
int index;
public ArgumentEnumerator(ILInstruction[] arguments)
{
this.arguments = arguments;
}
public bool MoveNext()
{
return ++index < arguments.Length;
}
public ILInstruction Current {
get { return arguments[index]; }
}
}
readonly ILInstruction[] arguments;
public readonly MethodReference Method;
public ArgumentCollection Arguments {
get { return new ArgumentCollection(this); }
}
protected CallInstruction(OpCode opCode, MethodReference methodReference) : base(opCode)
{
this.Method = methodReference;
int popCount = methodReference.Parameters.Count;
if (opCode != OpCode.NewObj && methodReference.HasThis)
popCount++;
ILInstruction[] operands = new ILInstruction[popCount];
for (int i = 0; i < operands.Length; i++) {
operands[i] = Pop;
this.arguments = new ILInstruction[popCount];
for (int i = 0; i < arguments.Length; i++) {
arguments[i] = Pop;
}
}
public override StackType ResultType {
get {
throw new NotImplementedException();
}
}
internal override void CheckInvariant()
{
base.CheckInvariant();
foreach (var op in arguments) {
op.CheckInvariant();
Debug.Assert(op.ResultType != StackType.Void);
}
return operands;
}
public override TAccumulate AggregateChildren<TSource, TAccumulate>(TAccumulate initial, ILVisitor<TSource> visitor, Func<TAccumulate, TSource, TAccumulate> func)
{
TAccumulate value = initial;
foreach (var op in arguments)
value = func(value, op.AcceptVisitor(visitor));
return value;
}
protected override InstructionFlags ComputeFlags()
{
var flags = InstructionFlags.MayThrow | InstructionFlags.SideEffects;
foreach (var op in arguments)
flags |= op.Flags;
return flags;
}
/*
public override bool IsPeeking { get { return Operands.Length > 0 && Operands[0].IsPeeking; } }
@ -66,10 +179,10 @@ namespace ICSharpCode.Decompiler.IL @@ -66,10 +179,10 @@ namespace ICSharpCode.Decompiler.IL
output.Write(' ');
Method.WriteTo(output);
output.Write('(');
for (int i = 0; i < Operands.Length; i++) {
for (int i = 0; i < Arguments.Length; i++) {
if (i > 0)
output.Write(", ");
Operands[i].WriteTo(output);
Arguments[i].WriteTo(output);
}
output.Write(')');
}

57
ICSharpCode.Decompiler/IL/Instructions/Conv.cs

@ -0,0 +1,57 @@ @@ -0,0 +1,57 @@
// 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;
namespace ICSharpCode.Decompiler.IL
{
partial class Conv : UnaryInstruction
{
public readonly StackType FromType;
public readonly PrimitiveType ToType;
public readonly OverflowMode ConvMode;
public Conv(StackType fromType, PrimitiveType toType, OverflowMode convMode) : base(OpCode.Conv)
{
this.FromType = fromType;
this.ToType = toType;
this.ConvMode = convMode;
}
public override void WriteTo(ITextOutput output)
{
output.Write(OpCode);
output.WriteSuffix(ConvMode);
output.Write(' ');
output.Write(FromType);
output.Write("->");
output.Write(ToType);
output.Write('(');
Argument.WriteTo(output);
output.Write(')');
}
protected override InstructionFlags ComputeFlags()
{
var flags = base.ComputeFlags();
if ((ConvMode & OverflowMode.Ovf) != 0)
flags |= InstructionFlags.MayThrow;
return flags;
}
}
}

73
ICSharpCode.Decompiler/IL/Instructions/ILInstruction.cs

@ -1,5 +1,24 @@ @@ -1,5 +1,24 @@
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;
using System.Text;
using System.Threading.Tasks;
@ -10,12 +29,45 @@ namespace ICSharpCode.Decompiler.IL @@ -10,12 +29,45 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>
/// Represents a decoded IL instruction
/// </summary>
public abstract class ILInstruction(OpCode opCode)
public abstract class ILInstruction
{
public static readonly ILInstruction Pop = new Pop();
public readonly OpCode OpCode;
protected ILInstruction(OpCode opCode)
{
this.OpCode = opCode;
}
public readonly OpCode OpCode = opCode;
[Conditional("DEBUG")]
internal virtual void CheckInvariant()
{
}
/// <summary>
/// Gets the stack type of the value produced by this instruction.
/// </summary>
public abstract StackType ResultType { get; }
InstructionFlags flags = (InstructionFlags)-1;
public InstructionFlags Flags {
get {
if (flags == (InstructionFlags)-1) {
flags = ComputeFlags();
}
return flags;
}
}
protected void InvalidateFlags()
{
flags = (InstructionFlags)-1;
}
protected abstract InstructionFlags ComputeFlags();
/// <summary>
/// Gets the ILRange for this instruction alone, ignoring the operands.
/// </summary>
@ -32,8 +84,17 @@ namespace ICSharpCode.Decompiler.IL @@ -32,8 +84,17 @@ namespace ICSharpCode.Decompiler.IL
get { return true; }
}
public abstract TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor);
public abstract T AcceptVisitor<T>(ILVisitor<T> visitor);
/// <summary>
/// Computes an aggregate value over the direct children of this instruction.
/// </summary>
/// <param name="initial">The initial value used to initialize the accumulator.</param>
/// <param name="visitor">The visitor used to compute the value for the child instructions.</param>
/// <param name="func">The function that combines the accumulator with the computed child value.</param>
/// <returns>The final value in the accumulator.</returns>
public abstract TAccumulate AggregateChildren<TSource, TAccumulate>(TAccumulate initial, ILVisitor<TSource> visitor, Func<TAccumulate, TSource, TAccumulate> func);
/*
/// <summary>
/// Gets whether this instruction peeks at the top value of the stack.

58
ICSharpCode.Decompiler/IL/Instructions/Return.cs

@ -0,0 +1,58 @@ @@ -0,0 +1,58 @@
// 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;
namespace ICSharpCode.Decompiler.IL
{
partial class Return
{
/// <summary>
/// The value to return. Null if this return statement is within a void method.
/// </summary>
public ILInstruction Argument = null;
internal override void CheckInvariant()
{
base.CheckInvariant();
if (Argument != null) {
Argument.CheckInvariant();
Debug.Assert(Argument.ResultType != StackType.Void);
}
}
public override void WriteTo(ITextOutput output)
{
output.Write(OpCode);
if (Argument != null) {
output.Write('(');
Argument.WriteTo(output);
output.Write(')');
}
}
public override TAccumulate AggregateChildren<TSource, TAccumulate>(TAccumulate initial, ILVisitor<TSource> visitor, Func<TAccumulate, TSource, TAccumulate> func)
{
TAccumulate value = initial;
if (Argument != null)
value = func(value, Argument.AcceptVisitor(visitor));
return value;
}
}
}

38
ICSharpCode.Decompiler/IL/Instructions/SimpleInstruction.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.Linq;
using System.Text;
@ -9,13 +27,27 @@ namespace ICSharpCode.Decompiler.IL @@ -9,13 +27,27 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>
/// A simple instruction that does not have any arguments.
/// </summary>
public abstract class SimpleInstruction(OpCode opCode) : ILInstruction(opCode)
public abstract class SimpleInstruction : ILInstruction
{
protected SimpleInstruction(OpCode opCode) : base(opCode)
{
}
public override void WriteTo(ITextOutput output)
{
output.Write(OpCode);
}
public sealed override TAccumulate AggregateChildren<TSource, TAccumulate>(TAccumulate initial, ILVisitor<TSource> visitor, Func<TAccumulate, TSource, TAccumulate> func)
{
return initial;
}
protected override InstructionFlags ComputeFlags()
{
return InstructionFlags.None;
}
/*public override bool IsPeeking { get { return false; } }
public override void TransformChildren(Func<ILInstruction, ILInstruction> transformFunc)

60
ICSharpCode.Decompiler/IL/Instructions/UnaryInstruction.cs

@ -1,17 +1,51 @@ @@ -1,17 +1,51 @@
using ICSharpCode.Decompiler.Disassembler;
using Mono.Cecil;
// 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;
using System.Text;
using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.IL
{
public abstract class UnaryInstruction(OpCode opCode) : ILInstruction(opCode)
public abstract class UnaryInstruction : ILInstruction
{
public ILInstruction Argument = Pop;
ILInstruction argument = Pop;
public ILInstruction Argument {
get { return argument; }
set {
Debug.Assert(value.ResultType != StackType.Void);
argument = value;
InvalidateFlags();
}
}
protected UnaryInstruction(OpCode opCode) : base(opCode)
{
}
internal override void CheckInvariant()
{
base.CheckInvariant();
Argument.CheckInvariant();
Debug.Assert(Argument.ResultType != StackType.Void);
}
//public sealed override bool IsPeeking { get { return Operand.IsPeeking; } }
public override void WriteTo(ITextOutput output)
@ -21,7 +55,17 @@ namespace ICSharpCode.Decompiler.IL @@ -21,7 +55,17 @@ namespace ICSharpCode.Decompiler.IL
Argument.WriteTo(output);
output.Write(')');
}
public sealed override TAccumulate AggregateChildren<TSource, TAccumulate>(TAccumulate initial, ILVisitor<TSource> visitor, Func<TAccumulate, TSource, TAccumulate> func)
{
return func(initial, Argument.AcceptVisitor(visitor));
}
protected override InstructionFlags ComputeFlags()
{
return Argument.Flags;
}
/*
public override void TransformChildren(Func<ILInstruction, ILInstruction> transformFunc)
{

22
ICSharpCode.Decompiler/IL/PrimitiveType.cs

@ -1,4 +1,22 @@ @@ -1,4 +1,22 @@
using Mono.Cecil;
// 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 Mono.Cecil;
using System;
using System.Collections.Generic;
using System.Linq;
@ -7,7 +25,7 @@ using System.Threading.Tasks; @@ -7,7 +25,7 @@ using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.IL
{
enum PrimitiveType : byte
public enum PrimitiveType : byte
{
None = 0,
I1 = MetadataType.SByte,

20
ICSharpCode.Decompiler/IL/SemanticHelper.cs

@ -1,8 +1,26 @@ @@ -1,8 +1,26 @@
// 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;
namespace ICSharpCode.Decompiler.IL
{
internal class SemanticHelper
static class SemanticHelper
{
/// <summary>
/// Gets whether the instruction sequence 'inst1; inst2;' may be ordered to 'inst2; inst1;'

20
ICSharpCode.Decompiler/IL/StackType.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.Linq;
using System.Text;

40
ICSharpCode.Decompiler/IL/Visitors/CountPopInstructionsVisitor.cs

@ -0,0 +1,40 @@ @@ -0,0 +1,40 @@
// 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;
namespace ICSharpCode.Decompiler.IL.Visitors
{
sealed class CountPopInstructionsVisitor : ILVisitor<int>
{
protected override int Default(ILInstruction inst)
{
return inst.AggregateChildren(0, this, (a, b) => a + b);
}
protected internal override int VisitPop(Pop inst)
{
return 1;
}
protected internal override int VisitBlock(Block inst)
{
throw new NotImplementedException();
}
}
}

9
ICSharpCode.Decompiler/Util/Interval.cs

@ -48,10 +48,15 @@ namespace ICSharpCode.Decompiler @@ -48,10 +48,15 @@ namespace ICSharpCode.Decompiler
/// <summary>
/// An immutable set of integers, that is implemented as a list of intervals.
/// </summary>
struct IntegerSet(ImmutableArray<Interval> intervals)
struct IntegerSet
{
public readonly ImmutableArray<Interval> Intervals = intervals;
public readonly ImmutableArray<Interval> Intervals;
public IntegerSet(ImmutableArray<Interval> intervals)
{
this.Intervals = intervals;
}
public bool IsEmpty
{
get { return Intervals.IsDefaultOrEmpty; }

Loading…
Cancel
Save