Browse Source

Use code generation to create the ILAst classes.

pull/728/head
Daniel Grunwald 11 years ago
parent
commit
75b0e23ae2
  1. 37
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  2. 33
      ICSharpCode.Decompiler/CSharp/StatementBuilder.cs
  3. 17
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  4. 9
      ICSharpCode.Decompiler/IL/ILReader.cs
  5. 869
      ICSharpCode.Decompiler/IL/Instructions.cs
  6. 212
      ICSharpCode.Decompiler/IL/Instructions.tt
  7. 19
      ICSharpCode.Decompiler/IL/Instructions/BinaryInstruction.cs
  8. 14
      ICSharpCode.Decompiler/IL/Instructions/Block.cs
  9. 8
      ICSharpCode.Decompiler/IL/Instructions/CallInstruction.cs
  10. 16
      ICSharpCode.Decompiler/IL/Instructions/ILInstruction.cs
  11. 14
      ICSharpCode.Decompiler/IL/Instructions/SimpleInstruction.cs
  12. 14
      ICSharpCode.Decompiler/IL/Instructions/UnaryInstruction.cs
  13. 2
      ICSharpCode.Decompiler/IL/StackType.cs

37
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -12,41 +12,46 @@ namespace ICSharpCode.Decompiler.CSharp @@ -12,41 +12,46 @@ namespace ICSharpCode.Decompiler.CSharp
/// <summary>
/// Translates from ILAst to C# expressions.
/// </summary>
class ExpressionBuilder(ICompilation compilation)
class ExpressionBuilder(ICompilation compilation) : ILVisitor<ExpressionBuilder.ConvertedExpression>
{
struct ConvertedExpression(Expression expression, IType type) {
private readonly ICompilation compilation = compilation;
internal struct ConvertedExpression(Expression expression, IType type) {
public readonly Expression Expression = expression;
public readonly IType Type = type;
}
public Expression Convert(ILInstruction inst)
{
var expr = TransformExpression(inst).Expression;
var expr = inst.AcceptVisitor(this).Expression;
expr.AddAnnotation(inst);
return expr;
}
ConvertedExpression ConvertArgument(ILInstruction inst)
{
var cexpr = TransformExpression(inst);
var cexpr = inst.AcceptVisitor(this);
cexpr.Expression.AddAnnotation(inst);
return cexpr;
}
ConvertedExpression TransformExpression(ILInstruction inst)
protected internal override ConvertedExpression VisitLdcI4(LdcI4 inst)
{
return new ConvertedExpression(
new PrimitiveExpression(inst.Value),
compilation.FindType(KnownTypeCode.Int32));
}
protected internal override ConvertedExpression VisitLogicNot(LogicNot inst)
{
switch (inst.OpCode) {
case OpCode.LdcI4:
return new ConvertedExpression(
new PrimitiveExpression(((ConstantI4)inst).Value),
compilation.FindType(KnownTypeCode.Int32));
case OpCode.LogicNot:
return new ConvertedExpression(
new UnaryOperatorExpression(UnaryOperatorType.Not, ConvertCondition(((LogicNotInstruction)inst).Operand)),
return new ConvertedExpression(
new UnaryOperatorExpression(UnaryOperatorType.Not, ConvertCondition(inst.Argument)),
compilation.FindType(KnownTypeCode.Boolean));
default:
return ErrorExpression("OpCode not supported: " + inst.OpCode);
}
}
protected override ConvertedExpression Default(ILInstruction inst)
{
return ErrorExpression("OpCode not supported: " + inst.OpCode);
}
static ConvertedExpression ErrorExpression(string message)

33
ICSharpCode.Decompiler/CSharp/StatementBuilder.cs

@ -9,37 +9,34 @@ using System.Threading.Tasks; @@ -9,37 +9,34 @@ using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.CSharp
{
class StatementBuilder(ICompilation compilation)
class StatementBuilder(ICompilation compilation) : ILVisitor<Statement>
{
readonly ExpressionBuilder exprBuilder = new ExpressionBuilder(compilation);
public Statement Convert(ILInstruction inst)
{
switch (inst.OpCode) {
case OpCode.BlockContainer:
return ConvertBlockContainer((BlockContainer)inst);
case OpCode.Ret:
if (inst is ReturnVoidInstruction)
return new ReturnStatement().WithAnnotation(inst);
return new ReturnStatement(ConvertUnaryArg(inst)).WithAnnotation(inst);
case OpCode.Throw:
return new ThrowStatement(ConvertUnaryArg(inst)).WithAnnotation(inst);
case OpCode.ConditionalBranch:
return ConvertConditionalBranch((ConditionalBranch)inst);
default:
return new ExpressionStatement(exprBuilder.Convert(inst));
}
return inst.AcceptVisitor(this);
}
protected override Statement Default(ILInstruction inst)
{
return new ExpressionStatement(exprBuilder.Convert(inst));
}
private Statement ConvertConditionalBranch(ConditionalBranch inst)
protected internal override Statement VisitConditionalBranch(ConditionalBranch inst)
{
var condition = exprBuilder.ConvertCondition(inst.Condition);
return new IfElseStatement(condition, new GotoStatement(inst.TargetLabel));
}
private Expression ConvertUnaryArg(ILInstruction inst)
protected internal override Statement VisitBranch(Branch inst)
{
return new GotoStatement(inst.TargetLabel);
}
protected internal override Statement VisitBlockContainer(BlockContainer inst)
{
return exprBuilder.Convert(((UnaryInstruction)inst).Operand);
return ConvertBlockContainer(inst);
}
public BlockStatement ConvertBlockContainer(BlockContainer container)

17
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -67,6 +67,17 @@ @@ -67,6 +67,17 @@
<Compile Include="CSharp\ExpressionBuilder.cs" />
<Compile Include="CSharp\NRefactoryExtensions.cs" />
<Compile Include="CSharp\StatementBuilder.cs" />
<Compile Include="IL\Instructions.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Instructions.tt</DependentUpon>
</Compile>
<Compile Include="IL\Instructions\BinaryInstruction.cs" />
<Compile Include="IL\Instructions\Block.cs" />
<Compile Include="IL\Instructions\CallInstruction.cs" />
<Compile Include="IL\Instructions\ILInstruction.cs" />
<Compile Include="IL\Instructions\SimpleInstruction.cs" />
<Compile Include="IL\Instructions\UnaryInstruction.cs" />
<Compile Include="TypesHierarchyHelpers.cs" />
<Compile Include="CecilExtensions.cs" />
<Compile Include="Disassembler\DisassemblerHelpers.cs" />
@ -85,8 +96,6 @@ @@ -85,8 +96,6 @@
<Compile Include="IL\ILVariable.cs" />
<Compile Include="IL\InstructionFlags.cs" />
<Compile Include="IL\InstructionOutputExtensions.cs" />
<Compile Include="IL\Instructions\ILInstruction.cs" />
<Compile Include="IL\Instructions\OpCode.cs" />
<Compile Include="IL\PrimitiveType.cs" />
<Compile Include="IL\StackType.cs" />
<Compile Include="Output\ITextOutput.cs" />
@ -101,6 +110,10 @@ @@ -101,6 +110,10 @@
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>ILOpCodes.cs</LastGenOutput>
</None>
<None Include="IL\Instructions.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>Instructions.cs</LastGenOutput>
</None>
<None Include="packages.config" />
<None Include="Properties\AssemblyInfo.template.cs" />
</ItemGroup>

9
ICSharpCode.Decompiler/IL/ILReader.cs

@ -13,6 +13,9 @@ namespace ICSharpCode.Decompiler.IL @@ -13,6 +13,9 @@ namespace ICSharpCode.Decompiler.IL
{
public class ILReader(Mono.Cecil.Cil.MethodBody body, CancellationToken cancellationToken)
{
private readonly Mono.Cecil.Cil.MethodBody body = body;
private readonly CancellationToken cancellationToken = cancellationToken;
internal static ILOpCode ReadOpCode(ref BlobReader reader)
{
byte b = reader.ReadByte();
@ -222,7 +225,7 @@ namespace ICSharpCode.Decompiler.IL @@ -222,7 +225,7 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode.Clt_Un:
return Comparison(OpCode.Clt_Un, OpCode.Clt_Un);
case ILOpCode.Ckfinite:
return new Ckfinite();
return new CkFinite();
case ILOpCode.Conv_I1:
return Conv(PrimitiveType.I1, OverflowMode.None);
case ILOpCode.Conv_I2:
@ -341,7 +344,7 @@ namespace ICSharpCode.Decompiler.IL @@ -341,7 +344,7 @@ namespace ICSharpCode.Decompiler.IL
return LdcI4(reader.ReadSByte());
case ILOpCode.Ldnull:
stack.Push(StackType.O);
return new ConstantNull();
return new LdNull();
case ILOpCode.Ldstr:
return DecodeLdstr();
case ILOpCode.Ldftn:
@ -407,7 +410,7 @@ namespace ICSharpCode.Decompiler.IL @@ -407,7 +410,7 @@ namespace ICSharpCode.Decompiler.IL
return BinaryNumeric(OpCode.BitOr);
case ILOpCode.Pop:
stack.PopOrDefault();
return new VoidInstruction();
return new Void();
case ILOpCode.Rem:
return BinaryNumeric(OpCode.Rem, OverflowMode.None);
case ILOpCode.Rem_Un:

869
ICSharpCode.Decompiler/IL/Instructions.cs

@ -0,0 +1,869 @@ @@ -0,0 +1,869 @@
using System;
using Mono.Cecil;
namespace ICSharpCode.Decompiler.IL
{
/// <summary>
/// Enum representing the type of an <see cref="ILInstruction"/>.
/// </summary>
public enum OpCode
{
/// <summary>No operation. Takes 0 arguments and returns void.</summary>
Nop,
/// <summary>Pops the top of the evaluation stack and returns the value.</summary>
Pop,
/// <summary>Peeks at the top of the evaluation stack and returns the value. Corresponds to IL 'dup'.</summary>
Peek,
/// <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>
BlockContainer,
/// <summary>A block of IL instructions.</summary>
Block,
/// <summary>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).</summary>
LogicNot,
/// <summary>Adds two numbers.</summary>
Add,
/// <summary>Subtracts two numbers</summary>
Sub,
/// <summary>Multiplies two numbers</summary>
Mul,
/// <summary>Divides two numbers</summary>
Div,
/// <summary>Division remainder</summary>
Rem,
/// <summary>Unary negation</summary>
Neg,
/// <summary>Bitwise AND</summary>
BitAnd,
/// <summary>Bitwise OR</summary>
BitOr,
/// <summary>Bitwise XOR</summary>
BitXor,
/// <summary>Bitwise NOT</summary>
BitNot,
/// <summary>Retrieves the RuntimeArgumentHandle.</summary>
Arglist,
/// <summary><c>if (condition) goto target;</c>.</summary>
ConditionalBranch,
/// <summary><c>goto target;</c>.</summary>
Branch,
/// <summary>Breakpoint instruction</summary>
DebugBreak,
/// <summary>Compare equal. Returns 1 (of type I4) if two numbers or object references are equal; 0 otherwise.</summary>
Ceq,
/// <summary>Compare greater than. For integers, perform a signed comparison. For floating-point numbers, return 0 for unordered numbers.</summary>
Cgt,
/// <summary>Compare greater than (unordered/unsigned). For integers, perform a signed comparison. For floating-point numbers, return 1 for unordered numbers.</summary>
Cgt_Un,
/// <summary>Compare less than. For integers, perform a signed comparison. For floating-point numbers, return 0 for unordered numbers.</summary>
Clt,
/// <summary>Compare less than (unordered/unsigned). For integers, perform a signed comparison. For floating-point numbers, return 1 for unordered numbers.</summary>
Clt_Un,
/// <summary>Non-virtual method call.</summary>
Call,
/// <summary>Virtual method call.</summary>
CallVirt,
/// <summary>Checks that the float on top of the stack is not NaN or infinite.</summary>
CkFinite,
/// <summary>Numeric cast.</summary>
Conv,
/// <summary>Loads the value of a local variable. (ldarg/ldloc)</summary>
Ldloc,
/// <summary>Loads the address of a local variable. (ldarga/ldloca)</summary>
Ldloca,
/// <summary>Stores a value into a local variable. (starg/stloc)</summary>
Stloc,
/// <summary>Loads a constant string.</summary>
LdStr,
/// <summary>Loads a constant 32-bit integer.</summary>
LdcI4,
/// <summary>Loads a constant 64-bit integer.</summary>
LdcI8,
/// <summary>Loads a constant floating-point number.</summary>
LdcF,
/// <summary>Loads the null reference.</summary>
LdNull,
/// <summary>Returns from the current method or lambda.</summary>
Return,
/// <summary>Shift left</summary>
Shl,
/// <summary>Shift right</summary>
Shr,
/// <summary>Load instance field</summary>
Ldfld,
/// <summary>Load address of instance field</summary>
Ldflda,
/// <summary>Store value to instance field</summary>
Stfld,
/// <summary>Load static field</summary>
Ldsfld,
/// <summary>Load static field address</summary>
Ldsflda,
/// <summary>Store value to static field</summary>
Stsfld,
/// <summary>Test if object is instance of class or interface.</summary>
IsInst,
/// <summary>Indirect load (ref/pointer dereference).</summary>
LdInd,
/// <summary>Unbox a value.</summary>
UnboxAny,
/// <summary>Creates an object instance and calls the constructor.</summary>
NewObj,
/// <summary>Throws an exception.</summary>
Throw,
/// <summary>Returns the length of an array as 'native unsigned int'.</summary>
LdLen,
}
/// <summary>No operation. Takes 0 arguments and returns void.</summary>
public sealed partial class Nop() : SimpleInstruction(OpCode.Nop)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitNop(this);
}
}
/// <summary>Pops the top of the evaluation stack and returns the value.</summary>
public sealed partial class Pop() : SimpleInstruction(OpCode.Pop)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitPop(this);
}
}
/// <summary>Peeks at the top of the evaluation stack and returns the value. Corresponds to IL 'dup'.</summary>
public sealed partial class Peek() : SimpleInstruction(OpCode.Peek)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitPeek(this);
}
}
/// <summary>Ignore the arguments and produce void. Used to prevent the end result of an instruction from being pushed to the evaluation stack.</summary>
public sealed partial class Void() : UnaryInstruction(OpCode.Void)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitVoid(this);
}
}
/// <summary>A container of IL blocks.</summary>
public sealed partial class BlockContainer() : ILInstruction(OpCode.BlockContainer)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitBlockContainer(this);
}
}
/// <summary>A block of IL instructions.</summary>
public sealed partial class Block() : ILInstruction(OpCode.Block)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitBlock(this);
}
}
/// <summary>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).</summary>
public sealed partial class LogicNot() : UnaryInstruction(OpCode.LogicNot)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitLogicNot(this);
}
}
/// <summary>Adds two numbers.</summary>
public sealed partial class Add(StackType opType, OverflowMode overflowMode) : BinaryNumericInstruction(OpCode.Add, opType, overflowMode)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitAdd(this);
}
}
/// <summary>Subtracts two numbers</summary>
public sealed partial class Sub(StackType opType, OverflowMode overflowMode) : BinaryNumericInstruction(OpCode.Sub, opType, overflowMode)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitSub(this);
}
}
/// <summary>Multiplies two numbers</summary>
public sealed partial class Mul(StackType opType, OverflowMode overflowMode) : BinaryNumericInstruction(OpCode.Mul, opType, overflowMode)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitMul(this);
}
}
/// <summary>Divides two numbers</summary>
public sealed partial class Div(StackType opType, OverflowMode overflowMode) : BinaryNumericInstruction(OpCode.Div, opType, overflowMode)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitDiv(this);
}
}
/// <summary>Division remainder</summary>
public sealed partial class Rem(StackType opType, OverflowMode overflowMode) : BinaryNumericInstruction(OpCode.Rem, opType, overflowMode)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitRem(this);
}
}
/// <summary>Unary negation</summary>
public sealed partial class Neg() : UnaryInstruction(OpCode.Neg)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitNeg(this);
}
}
/// <summary>Bitwise AND</summary>
public sealed partial class BitAnd(StackType opType, OverflowMode overflowMode) : BinaryNumericInstruction(OpCode.BitAnd, opType, overflowMode)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitBitAnd(this);
}
}
/// <summary>Bitwise OR</summary>
public sealed partial class BitOr(StackType opType, OverflowMode overflowMode) : BinaryNumericInstruction(OpCode.BitOr, opType, overflowMode)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitBitOr(this);
}
}
/// <summary>Bitwise XOR</summary>
public sealed partial class BitXor(StackType opType, OverflowMode overflowMode) : BinaryNumericInstruction(OpCode.BitXor, opType, overflowMode)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitBitXor(this);
}
}
/// <summary>Bitwise NOT</summary>
public sealed partial class BitNot() : UnaryInstruction(OpCode.BitNot)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitBitNot(this);
}
}
/// <summary>Retrieves the RuntimeArgumentHandle.</summary>
public sealed partial class Arglist() : SimpleInstruction(OpCode.Arglist)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitArglist(this);
}
}
/// <summary><c>if (condition) goto target;</c>.</summary>
public sealed partial class ConditionalBranch() : UnaryInstruction(OpCode.ConditionalBranch)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitConditionalBranch(this);
}
}
/// <summary><c>goto target;</c>.</summary>
public sealed partial class Branch() : SimpleInstruction(OpCode.Branch)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitBranch(this);
}
}
/// <summary>Breakpoint instruction</summary>
public sealed partial class DebugBreak() : SimpleInstruction(OpCode.DebugBreak)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitDebugBreak(this);
}
}
/// <summary>Compare equal. Returns 1 (of type I4) if two numbers or object references are equal; 0 otherwise.</summary>
public sealed partial class Ceq(StackType opType) : BinaryComparisonInstruction(OpCode.Ceq, opType)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitCeq(this);
}
}
/// <summary>Compare greater than. For integers, perform a signed comparison. For floating-point numbers, return 0 for unordered numbers.</summary>
public sealed partial class Cgt(StackType opType) : BinaryComparisonInstruction(OpCode.Cgt, opType)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitCgt(this);
}
}
/// <summary>Compare greater than (unordered/unsigned). For integers, perform a signed comparison. For floating-point numbers, return 1 for unordered numbers.</summary>
public sealed partial class Cgt_Un(StackType opType) : BinaryComparisonInstruction(OpCode.Cgt_Un, opType)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitCgt_Un(this);
}
}
/// <summary>Compare less than. For integers, perform a signed comparison. For floating-point numbers, return 0 for unordered numbers.</summary>
public sealed partial class Clt(StackType opType) : BinaryComparisonInstruction(OpCode.Clt, opType)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitClt(this);
}
}
/// <summary>Compare less than (unordered/unsigned). For integers, perform a signed comparison. For floating-point numbers, return 1 for unordered numbers.</summary>
public sealed partial class Clt_Un(StackType opType) : BinaryComparisonInstruction(OpCode.Clt_Un, opType)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitClt_Un(this);
}
}
/// <summary>Non-virtual method call.</summary>
public sealed partial class Call(MethodReference method) : CallInstruction(OpCode.Call, method)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitCall(this);
}
}
/// <summary>Virtual method call.</summary>
public sealed partial class CallVirt(MethodReference method) : CallInstruction(OpCode.CallVirt, method)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitCallVirt(this);
}
}
/// <summary>Checks that the float on top of the stack is not NaN or infinite.</summary>
public sealed partial class CkFinite() : SimpleInstruction(OpCode.CkFinite)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitCkFinite(this);
}
}
/// <summary>Numeric cast.</summary>
public sealed partial class Conv() : UnaryInstruction(OpCode.Conv)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitConv(this);
}
}
/// <summary>Loads the value of a local variable. (ldarg/ldloc)</summary>
public sealed partial class Ldloc() : SimpleInstruction(OpCode.Ldloc)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitLdloc(this);
}
}
/// <summary>Loads the address of a local variable. (ldarga/ldloca)</summary>
public sealed partial class Ldloca() : SimpleInstruction(OpCode.Ldloca)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitLdloca(this);
}
}
/// <summary>Stores a value into a local variable. (starg/stloc)</summary>
public sealed partial class Stloc() : UnaryInstruction(OpCode.Stloc)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitStloc(this);
}
}
/// <summary>Loads a constant string.</summary>
public sealed partial class LdStr() : SimpleInstruction(OpCode.LdStr)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitLdStr(this);
}
}
/// <summary>Loads a constant 32-bit integer.</summary>
public sealed partial class LdcI4() : SimpleInstruction(OpCode.LdcI4)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitLdcI4(this);
}
}
/// <summary>Loads a constant 64-bit integer.</summary>
public sealed partial class LdcI8() : SimpleInstruction(OpCode.LdcI8)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitLdcI8(this);
}
}
/// <summary>Loads a constant floating-point number.</summary>
public sealed partial class LdcF() : SimpleInstruction(OpCode.LdcF)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitLdcF(this);
}
}
/// <summary>Loads the null reference.</summary>
public sealed partial class LdNull() : SimpleInstruction(OpCode.LdNull)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitLdNull(this);
}
}
/// <summary>Returns from the current method or lambda.</summary>
public sealed partial class Return() : ILInstruction(OpCode.Return)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitReturn(this);
}
}
/// <summary>Shift left</summary>
public sealed partial class Shl(StackType opType, OverflowMode overflowMode) : BinaryNumericInstruction(OpCode.Shl, opType, overflowMode)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitShl(this);
}
}
/// <summary>Shift right</summary>
public sealed partial class Shr(StackType opType, OverflowMode overflowMode) : BinaryNumericInstruction(OpCode.Shr, opType, overflowMode)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitShr(this);
}
}
/// <summary>Load instance field</summary>
public sealed partial class Ldfld() : UnaryInstruction(OpCode.Ldfld)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitLdfld(this);
}
}
/// <summary>Load address of instance field</summary>
public sealed partial class Ldflda() : UnaryInstruction(OpCode.Ldflda)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitLdflda(this);
}
}
/// <summary>Store value to instance field</summary>
public sealed partial class Stfld() : BinaryInstruction(OpCode.Stfld)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitStfld(this);
}
}
/// <summary>Load static field</summary>
public sealed partial class Ldsfld() : SimpleInstruction(OpCode.Ldsfld)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitLdsfld(this);
}
}
/// <summary>Load static field address</summary>
public sealed partial class Ldsflda() : SimpleInstruction(OpCode.Ldsflda)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitLdsflda(this);
}
}
/// <summary>Store value to static field</summary>
public sealed partial class Stsfld() : UnaryInstruction(OpCode.Stsfld)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitStsfld(this);
}
}
/// <summary>Test if object is instance of class or interface.</summary>
public sealed partial class IsInst() : UnaryInstruction(OpCode.IsInst)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitIsInst(this);
}
}
/// <summary>Indirect load (ref/pointer dereference).</summary>
public sealed partial class LdInd() : UnaryInstruction(OpCode.LdInd)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitLdInd(this);
}
}
/// <summary>Unbox a value.</summary>
public sealed partial class UnboxAny() : UnaryInstruction(OpCode.UnboxAny)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitUnboxAny(this);
}
}
/// <summary>Creates an object instance and calls the constructor.</summary>
public sealed partial class NewObj(MethodReference method) : CallInstruction(OpCode.NewObj, method)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitNewObj(this);
}
}
/// <summary>Throws an exception.</summary>
public sealed partial class Throw() : UnaryInstruction(OpCode.Throw)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitThrow(this);
}
}
/// <summary>Returns the length of an array as 'native unsigned int'.</summary>
public sealed partial class LdLen() : UnaryInstruction(OpCode.LdLen)
{
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.VisitLdLen(this);
}
}
public abstract class ILVisitor<TReturn>
{
protected abstract TReturn Default(ILInstruction inst);
protected internal virtual TReturn VisitNop(Nop inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitPop(Pop inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitPeek(Peek inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitVoid(Void inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitBlockContainer(BlockContainer inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitBlock(Block inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitLogicNot(LogicNot inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitAdd(Add inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitSub(Sub inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitMul(Mul inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitDiv(Div inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitRem(Rem inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitNeg(Neg inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitBitAnd(BitAnd inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitBitOr(BitOr inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitBitXor(BitXor inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitBitNot(BitNot inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitArglist(Arglist inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitConditionalBranch(ConditionalBranch inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitBranch(Branch inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitDebugBreak(DebugBreak inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitCeq(Ceq inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitCgt(Cgt inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitCgt_Un(Cgt_Un inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitClt(Clt inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitClt_Un(Clt_Un inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitCall(Call inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitCallVirt(CallVirt inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitCkFinite(CkFinite inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitConv(Conv inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitLdloc(Ldloc inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitLdloca(Ldloca inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitStloc(Stloc inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitLdStr(LdStr inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitLdcI4(LdcI4 inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitLdcI8(LdcI8 inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitLdcF(LdcF inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitLdNull(LdNull inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitReturn(Return inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitShl(Shl inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitShr(Shr inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitLdfld(Ldfld inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitLdflda(Ldflda inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitStfld(Stfld inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitLdsfld(Ldsfld inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitLdsflda(Ldsflda inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitStsfld(Stsfld inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitIsInst(IsInst inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitLdInd(LdInd inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitUnboxAny(UnboxAny inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitNewObj(NewObj inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitThrow(Throw inst)
{
return Default(inst);
}
protected internal virtual TReturn VisitLdLen(LdLen inst)
{
return Default(inst);
}
}
}

212
ICSharpCode.Decompiler/IL/Instructions.tt

@ -0,0 +1,212 @@ @@ -0,0 +1,212 @@
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ 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("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("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("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("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("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),
};
#>
using System;
using Mono.Cecil;
namespace ICSharpCode.Decompiler.IL
{
/// <summary>
/// Enum representing the type of an <see cref="ILInstruction"/>.
/// </summary>
public enum OpCode
{
<# foreach (OpCode opCode in opCodes) { #>
/// <summary><#=opCode.Description#></summary>
<#=opCode.Name#>,
<# } #>
}
<# 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)#>)
{
<#=string.Join(Environment.NewLine, opCode.Members)#>
public override TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor)
{
return visitor.Visit<#=opCode.Name#>(this);
}
}
<# } #>
public abstract class ILVisitor<TReturn>
{
protected abstract TReturn Default(ILInstruction inst);
<# foreach (OpCode opCode in opCodes) { #>
protected internal virtual TReturn Visit<#=opCode.Name#>(<#=opCode.Name#> inst)
{
return Default(inst);
}
<# } #>
}
}
<#+
class OpCode {
public readonly string Name;
public readonly string Description;
public OpCode(string name, string description, params Action<OpCode>[] traits)
{
this.Name = name;
this.Description = description;
this.BaseConstructorArguments.Add("OpCode." + name);
foreach (var trait in traits)
trait(this);
}
public List<string> ConstructorParameters = new List<string>();
public string BaseClass = "ILInstruction";
public List<string> BaseConstructorArguments = new List<string>();
public List<string> Members = new List<string>();
}
// Peeking trait: the instruction looks at the top-of-stack without popping
static Action<OpCode> Peeking = opCode => { };
// 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 => { };
// 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;
// MayThrow trait: the instruction may throw exceptions
static Action<OpCode> MayThrow = opCode => {};
// MayBranch trait: the instruction may cause control flow to branch (e.g. branch, conditionalbranch, return)
static Action<OpCode> MayBranch = opCode => {};
// 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 => {};
// NoArguments trait: the instruction no arguments
static Action<OpCode> NoArguments = opCode => {
opCode.BaseClass = "SimpleInstruction";
};
// Unary trait: the instruction has a single argument
static Action<OpCode> Unary = opCode => {
opCode.BaseClass = "UnaryInstruction";
};
// Binary trait: the instruction has two arguments named 'Left' and 'Right'
static Action<OpCode> Binary = opCode => {
opCode.BaseClass = "BinaryInstruction";
};
// BinaryNumeric trait: the instruction is derived from BinaryNumericInstruction. Implies Binary and NonVoidResult; and implies MayThrow if the overflow mode is checked.
static Action<OpCode> BinaryNumeric = opCode => {
opCode.BaseClass = "BinaryNumericInstruction";
opCode.ConstructorParameters.Add("StackType opType");
opCode.ConstructorParameters.Add("OverflowMode overflowMode");
opCode.BaseConstructorArguments.Add("opType");
opCode.BaseConstructorArguments.Add("overflowMode");
};
// BinaryNumeric trait: the instruction is derived from BinaryComparisonInstruction. Implies Binary and I4Result.
static Action<OpCode> BinaryComparison = opCode => {
opCode.BaseClass = "BinaryComparisonInstruction";
opCode.ConstructorParameters.Add("StackType opType");
opCode.BaseConstructorArguments.Add("opType");
};
// SideEffect trait: the instruction has a non-local side effect
static Action<OpCode> SideEffect = opCode => {};
// Call trait: the instruction performs a method call
static Action<OpCode> Call = opCode => {
opCode.BaseClass = "CallInstruction";
opCode.ConstructorParameters.Add("MethodReference method");
opCode.BaseConstructorArguments.Add("method");
};
// HasVariableOperand trait: the instruction refers to a local variable
static Action<OpCode> HasVariableOperand = opCode => {};
static Action<OpCode> HasFieldOperand = opCode => {};
static Action<OpCode> HasTypeOperand = opCode => {};
// LoadConstant trait: the instruction loads a compile-time constant. Implies NoArguments and NonVoidResult
static Action<OpCode> LoadConstant = opCode => {
NoArguments(opCode);
NonVoidResult(opCode);
};
#>

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

@ -6,11 +6,12 @@ using System.Threading.Tasks; @@ -6,11 +6,12 @@ using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.IL
{
abstract class BinaryInstruction(OpCode opCode) : ILInstruction(opCode)
public abstract class BinaryInstruction(OpCode opCode) : ILInstruction(opCode)
{
public ILInstruction Left = Pop;
public ILInstruction Right = Pop;
/*
public override bool IsPeeking { get { return Left.IsPeeking; } }
public override void TransformChildren(Func<ILInstruction, ILInstruction> transformFunc)
@ -26,10 +27,10 @@ namespace ICSharpCode.Decompiler.IL @@ -26,10 +27,10 @@ namespace ICSharpCode.Decompiler.IL
if (finished)
Left = Left.Inline(flagsBefore, instructionStack, out finished);
return this;
}
}*/
}
class BinaryNumericInstruction(OpCode opCode, StackType opType, OverflowMode overflowMode)
public abstract class BinaryNumericInstruction(OpCode opCode, StackType opType, OverflowMode overflowMode)
: BinaryInstruction(opCode)
{
public readonly StackType OpType = opType;
@ -47,14 +48,9 @@ namespace ICSharpCode.Decompiler.IL @@ -47,14 +48,9 @@ namespace ICSharpCode.Decompiler.IL
Right.WriteTo(output);
output.Write(')');
}
public override InstructionFlags Flags
{
get { return Left.Flags | Right.Flags | InstructionFlags.MayThrow; }
}
}
class BinaryComparisonInstruction(OpCode opCode, StackType opType)
public abstract class BinaryComparisonInstruction(OpCode opCode, StackType opType)
: BinaryInstruction(opCode)
{
public readonly StackType OpType = opType;
@ -70,11 +66,6 @@ namespace ICSharpCode.Decompiler.IL @@ -70,11 +66,6 @@ namespace ICSharpCode.Decompiler.IL
Right.WriteTo(output);
output.Write(')');
}
public override InstructionFlags Flags
{
get { return Left.Flags | Right.Flags; }
}
}
public enum OverflowMode : byte

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

@ -9,10 +9,11 @@ namespace ICSharpCode.Decompiler.IL @@ -9,10 +9,11 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>
/// A block of IL instructions.
/// </summary>
class Block() : ILInstruction(OpCode.Block)
partial class Block : ILInstruction
{
public readonly List<ILInstruction> Instructions = new List<ILInstruction>();
/*
public override bool IsPeeking { get { return Instructions.Count > 0 && Instructions[0].IsPeeking; } }
public override bool NoResult { get { return true; } }
@ -23,6 +24,7 @@ namespace ICSharpCode.Decompiler.IL @@ -23,6 +24,7 @@ namespace ICSharpCode.Decompiler.IL
Instructions[i] = transformFunc(Instructions[i]);
}
}
*/
/// <summary>
/// Gets the name of this block.
@ -45,6 +47,7 @@ namespace ICSharpCode.Decompiler.IL @@ -45,6 +47,7 @@ namespace ICSharpCode.Decompiler.IL
output.WriteLine("}");
}
/*
public override InstructionFlags Flags
{
get {
@ -63,7 +66,7 @@ namespace ICSharpCode.Decompiler.IL @@ -63,7 +66,7 @@ namespace ICSharpCode.Decompiler.IL
else
finished = true;
return this;
}
}*/
}
/// <summary>
@ -73,11 +76,12 @@ namespace ICSharpCode.Decompiler.IL @@ -73,11 +76,12 @@ namespace ICSharpCode.Decompiler.IL
/// That means that viewed from the outside, the block container has a single entry point (but possibly multiple exit points),
/// and the same holds for every block within the container.
/// </summary>
class BlockContainer() : ILInstruction(OpCode.BlockContainer)
partial class BlockContainer : ILInstruction
{
public List<Block> Blocks = new List<Block>();
public Block EntryPoint { get { return Blocks[0]; } }
/*
public override bool IsPeeking { get { return EntryPoint.IsPeeking; } }
public override bool NoResult { get { return true; } }
@ -89,6 +93,7 @@ namespace ICSharpCode.Decompiler.IL @@ -89,6 +93,7 @@ namespace ICSharpCode.Decompiler.IL
throw new InvalidOperationException("Cannot replace blocks");
}
}
*/
public override void WriteTo(ITextOutput output)
{
@ -102,6 +107,7 @@ namespace ICSharpCode.Decompiler.IL @@ -102,6 +107,7 @@ namespace ICSharpCode.Decompiler.IL
output.WriteLine("}");
}
/*
public override InstructionFlags Flags
{
get
@ -118,6 +124,6 @@ namespace ICSharpCode.Decompiler.IL @@ -118,6 +124,6 @@ namespace ICSharpCode.Decompiler.IL
{
finished = false;
return this;
}
}*/
}
}

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

@ -8,7 +8,7 @@ using System.Threading.Tasks; @@ -8,7 +8,7 @@ using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.IL
{
class CallInstruction(OpCode opCode, MethodReference methodReference) : ILInstruction(opCode)
public abstract class CallInstruction(OpCode opCode, MethodReference methodReference) : ILInstruction(opCode)
{
public readonly MethodReference Method = methodReference;
public readonly ILInstruction[] Operands = InitOperands(opCode, methodReference);
@ -25,6 +25,7 @@ namespace ICSharpCode.Decompiler.IL @@ -25,6 +25,7 @@ namespace ICSharpCode.Decompiler.IL
return operands;
}
/*
public override bool IsPeeking { get { return Operands.Length > 0 && Operands[0].IsPeeking; } }
public override bool NoResult
@ -40,7 +41,7 @@ namespace ICSharpCode.Decompiler.IL @@ -40,7 +41,7 @@ namespace ICSharpCode.Decompiler.IL
for (int i = 0; i < Operands.Length; i++) {
Operands[i] = transformFunc(Operands[i]);
}
}
}*/
/// <summary>
/// Gets/Sets whether the call has the 'tail.' prefix.
@ -73,6 +74,7 @@ namespace ICSharpCode.Decompiler.IL @@ -73,6 +74,7 @@ namespace ICSharpCode.Decompiler.IL
output.Write(')');
}
/*
public override InstructionFlags Flags
{
get
@ -99,6 +101,6 @@ namespace ICSharpCode.Decompiler.IL @@ -99,6 +101,6 @@ namespace ICSharpCode.Decompiler.IL
break;
}
return this;
}
}*/
}
}

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

@ -3,6 +3,7 @@ using System.Collections.Generic; @@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ICSharpCode.Decompiler.CSharp;
namespace ICSharpCode.Decompiler.IL
{
@ -20,6 +21,20 @@ namespace ICSharpCode.Decompiler.IL @@ -20,6 +21,20 @@ namespace ICSharpCode.Decompiler.IL
/// </summary>
public Interval ILRange;
public abstract void WriteTo(ITextOutput output);
/// <summary>
/// Gets whether the end point of this instruction is reachable from the start point.
/// Returns false if the instruction performs an unconditional branch, or always throws an exception.
/// </summary>
public virtual bool IsEndReachable
{
get { return true; }
}
public abstract TReturn AcceptVisitor<TReturn>(ILVisitor<TReturn> visitor);
/*
/// <summary>
/// Gets whether this instruction peeks at the top value of the stack.
/// If this instruction also pops elements from the stack, this property refers to the top value
@ -63,5 +78,6 @@ namespace ICSharpCode.Decompiler.IL @@ -63,5 +78,6 @@ namespace ICSharpCode.Decompiler.IL
internal abstract ILInstruction Inline(InstructionFlags flagsBefore, Stack<ILInstruction> instructionStack, out bool finished);
public abstract void TransformChildren(Func<ILInstruction, ILInstruction> transformFunc);
*/
}
}

14
ICSharpCode.Decompiler/IL/Instructions/SimpleInstruction.cs

@ -9,9 +9,14 @@ namespace ICSharpCode.Decompiler.IL @@ -9,9 +9,14 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>
/// A simple instruction that does not have any arguments.
/// </summary>
abstract class SimpleInstruction(OpCode opCode) : ILInstruction(opCode)
public abstract class SimpleInstruction(OpCode opCode) : ILInstruction(opCode)
{
public override bool IsPeeking { get { return false; } }
public override void WriteTo(ITextOutput output)
{
output.Write(OpCode);
}
/*public override bool IsPeeking { get { return false; } }
public override void TransformChildren(Func<ILInstruction, ILInstruction> transformFunc)
{
@ -21,9 +26,10 @@ namespace ICSharpCode.Decompiler.IL @@ -21,9 +26,10 @@ namespace ICSharpCode.Decompiler.IL
{
finished = true; // Nothing to do, since we don't have arguments.
return this;
}
}*/
}
/*
class Nop() : SimpleInstruction(OpCode.Nop)
{
public override bool NoResult { get { return true; } }
@ -159,5 +165,5 @@ namespace ICSharpCode.Decompiler.IL @@ -159,5 +165,5 @@ namespace ICSharpCode.Decompiler.IL
{
get { return InstructionFlags.None; }
}
}
}*/
}

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

@ -8,20 +8,21 @@ using System.Threading.Tasks; @@ -8,20 +8,21 @@ using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.IL
{
abstract class UnaryInstruction(OpCode opCode) : ILInstruction(opCode)
public abstract class UnaryInstruction(OpCode opCode) : ILInstruction(opCode)
{
public ILInstruction Operand = Pop;
public ILInstruction Argument = Pop;
public sealed override bool IsPeeking { get { return Operand.IsPeeking; } }
//public sealed override bool IsPeeking { get { return Operand.IsPeeking; } }
public override void WriteTo(ITextOutput output)
{
output.Write(OpCode);
output.Write('(');
Operand.WriteTo(output);
Argument.WriteTo(output);
output.Write(')');
}
/*
public override void TransformChildren(Func<ILInstruction, ILInstruction> transformFunc)
{
Operand = transformFunc(Operand);
@ -31,9 +32,10 @@ namespace ICSharpCode.Decompiler.IL @@ -31,9 +32,10 @@ namespace ICSharpCode.Decompiler.IL
{
Operand = Operand.Inline(flagsBefore, instructionStack, out finished);
return this;
}
}*/
}
/*
class VoidInstruction() : UnaryInstruction(OpCode.Void)
{
public override bool NoResult { get { return true; } }
@ -111,6 +113,6 @@ namespace ICSharpCode.Decompiler.IL @@ -111,6 +113,6 @@ namespace ICSharpCode.Decompiler.IL
{
get { return Operand.Flags | InstructionFlags.MayThrow; }
}
}
}*/
}

2
ICSharpCode.Decompiler/IL/StackType.cs

@ -9,7 +9,7 @@ namespace ICSharpCode.Decompiler.IL @@ -9,7 +9,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>
/// A type for the purpose of stack analysis.
/// </summary>
enum StackType
public enum StackType
{
Unknown,
/// <summary>32-bit integer</summary>

Loading…
Cancel
Save