Browse Source

More instructions.

pull/728/head
Daniel Grunwald 11 years ago
parent
commit
e4eb208a2e
  1. 1
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  2. 79
      ICSharpCode.Decompiler/IL/ILReader.cs
  3. 6
      ICSharpCode.Decompiler/IL/Instructions/BinaryInstruction.cs
  4. 32
      ICSharpCode.Decompiler/IL/Instructions/BranchInstruction.cs
  5. 15
      ICSharpCode.Decompiler/IL/Instructions/CallInstruction.cs
  6. 88
      ICSharpCode.Decompiler/IL/Instructions/FieldAccess.cs
  7. 30
      ICSharpCode.Decompiler/IL/Instructions/ILInstruction.cs
  8. 66
      ICSharpCode.Decompiler/IL/Instructions/OpCode.cs
  9. 5
      ICSharpCode.Decompiler/IL/Instructions/Prefix.cs
  10. 48
      ICSharpCode.Decompiler/IL/Instructions/SimpleInstruction.cs
  11. 14
      ICSharpCode.Decompiler/IL/Instructions/UnaryInstruction.cs
  12. 19
      ICSharpCode.Decompiler/IL/Instructions/VarInstructions.cs

1
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -83,6 +83,7 @@ @@ -83,6 +83,7 @@
<Compile Include="IL\Instructions\Block.cs" />
<Compile Include="IL\Instructions\BranchInstruction.cs" />
<Compile Include="IL\Instructions\CallInstruction.cs" />
<Compile Include="IL\Instructions\FieldAccess.cs" />
<Compile Include="IL\Instructions\ILInstruction.cs" />
<Compile Include="IL\Instructions\OpCode.cs" />
<Compile Include="IL\Instructions\Prefix.cs" />

79
ICSharpCode.Decompiler/IL/ILReader.cs

@ -55,7 +55,7 @@ namespace ICSharpCode.Decompiler.IL @@ -55,7 +55,7 @@ namespace ICSharpCode.Decompiler.IL
ILInstruction decodedInstruction = DecodeInstruction();
decodedInstruction.ILRange = new Interval(start, reader.Position);
instructionBuilder.Add(decodedInstruction);
if ((var branch = decodedInstruction as BranchInstruction) != null) {
if ((var branch = decodedInstruction as Branch) != null) {
if (branch.TargetILOffset >= reader.Position) {
branchStackDict[branch.TargetILOffset] = stack.ToImmutableArray();
}
@ -70,7 +70,7 @@ namespace ICSharpCode.Decompiler.IL @@ -70,7 +70,7 @@ namespace ICSharpCode.Decompiler.IL
}
}
return instructionBuilder.ToImmutable();
}
}
private bool IsUnconditionalBranch(OpCode opCode)
{
@ -101,7 +101,7 @@ namespace ICSharpCode.Decompiler.IL @@ -101,7 +101,7 @@ namespace ICSharpCode.Decompiler.IL
return BinaryNumeric(OpCode.BitAnd);
case ILOpCode.Arglist:
stack.Push(StackType.O);
return new SimpleInstruction(OpCode.Arglist);
return new Arglist();
case ILOpCode.Beq:
return DecodeComparisonBranch(false, OpCode.Ceq, OpCode.Ceq, false);
case ILOpCode.Beq_S:
@ -147,7 +147,7 @@ namespace ICSharpCode.Decompiler.IL @@ -147,7 +147,7 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode.Br_S:
return DecodeUnconditionalBranch(true, OpCode.Branch);
case ILOpCode.Break:
return new SimpleInstruction(OpCode.Break);
return new DebugBreak();
case ILOpCode.Brfalse:
return DecodeConditionalBranch(false, true);
case ILOpCode.Brfalse_S:
@ -173,7 +173,7 @@ namespace ICSharpCode.Decompiler.IL @@ -173,7 +173,7 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode.Clt_Un:
return Comparison(OpCode.Clt_Un, OpCode.Clt_Un);
case ILOpCode.Ckfinite:
return new PeekInstruction(OpCode.Ckfinite);
return new Ckfinite();
case ILOpCode.Conv_I1:
return Conv(PrimitiveType.I1, OverflowMode.None);
case ILOpCode.Conv_I2:
@ -247,7 +247,7 @@ namespace ICSharpCode.Decompiler.IL @@ -247,7 +247,7 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode.Div_Un:
return BinaryNumeric(OpCode.Div, OverflowMode.Un);
case ILOpCode.Dup:
return new PeekInstruction(OpCode.Peek);
return new Peek();
case ILOpCode.Endfilter:
throw new NotImplementedException();
case ILOpCode.Endfinally:
@ -292,7 +292,7 @@ namespace ICSharpCode.Decompiler.IL @@ -292,7 +292,7 @@ namespace ICSharpCode.Decompiler.IL
return LdcI4(reader.ReadSByte());
case ILOpCode.Ldnull:
stack.Push(StackType.O);
return new SimpleInstruction(OpCode.LdNull);
return new ConstantNull();
case ILOpCode.Ldstr:
return DecodeLdstr();
case ILOpCode.Ldftn:
@ -337,14 +337,14 @@ namespace ICSharpCode.Decompiler.IL @@ -337,14 +337,14 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode.Neg:
return UnaryNumeric(OpCode.Neg);
case ILOpCode.Nop:
return new SimpleInstruction(OpCode.Nop);
return new Nop();
case ILOpCode.Not:
return UnaryNumeric(OpCode.BitNot);
case ILOpCode.Or:
return BinaryNumeric(OpCode.BitOr);
case ILOpCode.Pop:
stack.PopOrDefault();
return new UnaryInstruction(OpCode.Void);
return new VoidInstruction();
case ILOpCode.Rem:
return BinaryNumeric(OpCode.Rem, OverflowMode.None);
case ILOpCode.Rem_Un:
@ -406,21 +406,36 @@ namespace ICSharpCode.Decompiler.IL @@ -406,21 +406,36 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode.Ldelema:
throw new NotImplementedException();
case ILOpCode.Ldfld:
throw new NotImplementedException();
{
stack.PopOrDefault();
FieldReference field = (FieldReference)ReadAndDecodeMetadataToken();
stack.Push(field.FieldType.GetStackType());
return new LoadInstanceField(field);
}
case ILOpCode.Ldflda:
throw new NotImplementedException();
stack.PopOrDefault();
stack.Push(StackType.Ref);
return new LoadInstanceField((FieldReference)ReadAndDecodeMetadataToken(), OpCode.Ldflda);
case ILOpCode.Stfld:
throw new NotImplementedException();
stack.PopOrDefault();
stack.PopOrDefault();
return new StoreInstanceField((FieldReference)ReadAndDecodeMetadataToken());
case ILOpCode.Ldlen:
throw new NotImplementedException();
case ILOpCode.Ldobj:
throw new NotImplementedException();
case ILOpCode.Ldsfld:
throw new NotImplementedException();
{
FieldReference field = (FieldReference)ReadAndDecodeMetadataToken();
stack.Push(field.FieldType.GetStackType());
return new LoadStaticField(field);
}
case ILOpCode.Ldsflda:
throw new NotImplementedException();
stack.Push(StackType.Ref);
return new LoadStaticField((FieldReference)ReadAndDecodeMetadataToken(), OpCode.Ldsflda);
case ILOpCode.Stsfld:
throw new NotImplementedException();
stack.PopOrDefault();
return new StoreStaticField((FieldReference)ReadAndDecodeMetadataToken());
case ILOpCode.Ldtoken:
throw new NotImplementedException();
case ILOpCode.Ldvirtftn:
@ -470,9 +485,9 @@ namespace ICSharpCode.Decompiler.IL @@ -470,9 +485,9 @@ namespace ICSharpCode.Decompiler.IL
private ILInstruction Ret()
{
if (body.Method.ReturnType.GetStackType() == StackType.Void)
return new SimpleInstruction(OpCode.Ret);
return new RetVoid();
else
return new UnaryInstruction(OpCode.Ret);
return new Ret();
}
private ILInstruction UnaryNumeric(OpCode opCode)
@ -486,61 +501,61 @@ namespace ICSharpCode.Decompiler.IL @@ -486,61 +501,61 @@ namespace ICSharpCode.Decompiler.IL
{
stack.Push(StackType.O);
var metadataToken = ReadMetadataToken(ref reader);
return new ConstantStringInstruction(body.LookupStringToken(metadataToken));
}
return new ConstantString(body.LookupStringToken(metadataToken));
}
private ILInstruction LdcI4(int val)
{
stack.Push(StackType.I4);
return new ConstantI4Instruction(val);
return new ConstantI4(val);
}
private ILInstruction LdcI8(long val)
{
stack.Push(StackType.I8);
return new ConstantI8Instruction(val);
return new ConstantI8(val);
}
private ILInstruction LdcF(double val)
{
stack.Push(StackType.F);
return new ConstantFloatInstruction(val);
return new ConstantFloat(val);
}
private ILInstruction Ldarg(ushort v)
{
stack.Push(parameterVariables[v].Type.GetStackType());
return new LoadVarInstruction(parameterVariables[v]);
}
return new LdLoc(parameterVariables[v]);
}
private ILInstruction Ldarga(ushort v)
{
stack.Push(StackType.Ref);
return new LoadVarInstruction(parameterVariables[v], OpCode.LoadVarAddress);
return new LdLoca(parameterVariables[v]);
}
private ILInstruction Starg(ushort v)
{
stack.PopOrDefault();
return new StoreVarInstruction(parameterVariables[v]);
return new StLoc(parameterVariables[v]);
}
private ILInstruction Ldloc(ushort v)
{
stack.Push(localVariables[v].Type.GetStackType());
return new LoadVarInstruction(localVariables[v]);
return new LdLoc(localVariables[v]);
}
private ILInstruction Ldloca(ushort v)
{
stack.Push(StackType.Ref);
return new LoadVarInstruction(localVariables[v], OpCode.LoadVarAddress);
return new LdLoca(localVariables[v]);
}
private ILInstruction Stloc(ushort v)
{
stack.PopOrDefault();
return new StoreVarInstruction(localVariables[v]);
return new StLoc(localVariables[v]);
}
private ILInstruction DecodeConstrainedCall()
@ -619,7 +634,7 @@ namespace ICSharpCode.Decompiler.IL @@ -619,7 +634,7 @@ namespace ICSharpCode.Decompiler.IL
if (negate) {
condition = new LogicNotInstruction { Operand = condition };
}
return new ConditionalBranchInstruction(condition, target);
return new ConditionalBranch(condition, target);
}
ILInstruction DecodeConditionalBranch(bool shortForm, bool negate)
@ -630,14 +645,14 @@ namespace ICSharpCode.Decompiler.IL @@ -630,14 +645,14 @@ namespace ICSharpCode.Decompiler.IL
if (negate) {
condition = new LogicNotInstruction { Operand = condition };
}
return new ConditionalBranchInstruction(condition, target);
return new ConditionalBranch(condition, target);
}
ILInstruction DecodeUnconditionalBranch(bool shortForm, OpCode opCode)
{
int start = reader.Position - 1;
int target = start + (shortForm ? reader.ReadSByte() : reader.ReadInt32());
return new BranchInstruction(opCode, target);
return new Branch(opCode, target);
}
ILInstruction BinaryNumeric(OpCode opCode, OverflowMode overflowMode = OverflowMode.None)

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

@ -12,6 +12,12 @@ namespace ICSharpCode.Decompiler.IL @@ -12,6 +12,12 @@ namespace ICSharpCode.Decompiler.IL
public ILInstruction Right = Pop;
public override bool IsPeeking { get { return Left.IsPeeking; } }
public override void TransformChildren(Func<ILInstruction, ILInstruction> transformFunc)
{
Left = transformFunc(Left);
Right = transformFunc(Right);
}
}
class BinaryNumericInstruction(OpCode opCode, StackType opType, OverflowMode overflowMode)

32
ICSharpCode.Decompiler/IL/Instructions/BranchInstruction.cs

@ -9,7 +9,7 @@ namespace ICSharpCode.Decompiler.IL @@ -9,7 +9,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>
/// Base class for unconditional and conditional branches.
/// </summary>
class BranchInstruction(OpCode opCode, public int TargetILOffset) : ILInstruction(opCode)
class Branch(OpCode opCode, public int TargetILOffset) : ILInstruction(opCode)
{
public override bool IsPeeking { get { return false; } }
@ -19,13 +19,26 @@ namespace ICSharpCode.Decompiler.IL @@ -19,13 +19,26 @@ namespace ICSharpCode.Decompiler.IL
output.Write(' ');
output.WriteReference(CecilExtensions.OffsetToString(TargetILOffset), TargetILOffset, isLocal: true);
}
public override bool IsEndReachable
{
get
{
// end is reachable for conditional branches, but not unconditional ones
return OpCode == OpCode.ConditionalBranch;
}
}
public override void TransformChildren(Func<ILInstruction, ILInstruction> transformFunc)
{
}
}
/// <summary>
/// Special instruction for unresolved branches.
/// Created by ILReader phase, replaced with TODO when building basic blocks.
/// </summary>
class ConditionalBranchInstruction(public ILInstruction Condition, int targetILOffset) : BranchInstruction(OpCode.ConditionalBranch, targetILOffset)
class ConditionalBranch(public ILInstruction Condition, int targetILOffset) : Branch(OpCode.ConditionalBranch, targetILOffset)
{
public override bool IsPeeking { get { return Condition.IsPeeking; } }
@ -36,5 +49,20 @@ namespace ICSharpCode.Decompiler.IL @@ -36,5 +49,20 @@ namespace ICSharpCode.Decompiler.IL
Condition.WriteTo(output);
output.Write(')');
}
public override void TransformChildren(Func<ILInstruction, ILInstruction> transformFunc)
{
Condition = transformFunc(Condition);
}
}
class RetVoid() : SimpleInstruction(OpCode.Ret)
{
public override bool IsEndReachable { get { return false; } }
}
class Ret() : UnaryInstruction(OpCode.Ret)
{
public override bool IsEndReachable { get { return false; } }
}
}

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

@ -24,6 +24,21 @@ namespace ICSharpCode.Decompiler.IL @@ -24,6 +24,21 @@ namespace ICSharpCode.Decompiler.IL
public override bool IsPeeking { get { return Operands.Length > 0 && Operands[0].IsPeeking; } }
public override bool NoResult
{
get
{
return Method.ReturnType.GetStackType() == StackType.Void;
}
}
public override void TransformChildren(Func<ILInstruction, ILInstruction> transformFunc)
{
for (int i = 0; i < Operands.Length; i++) {
Operands[i] = transformFunc(Operands[i]);
}
}
/// <summary>
/// Gets/Sets whether the call has the 'tail.' prefix.
/// </summary>

88
ICSharpCode.Decompiler/IL/Instructions/FieldAccess.cs

@ -0,0 +1,88 @@ @@ -0,0 +1,88 @@
using Mono.Cecil;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.IL
{
class LoadStaticField(FieldReference field, OpCode opCode = OpCode.Ldsfld) : UnaryInstruction(opCode), ISupportsVolatilePrefix
{
public readonly FieldReference Field = field;
public bool IsVolatile { get; set; }
public override void WriteTo(ITextOutput output)
{
if (IsVolatile)
output.Write("volatile.");
output.Write(OpCode);
output.Write(' ');
Disassembler.DisassemblerHelpers.WriteOperand(output, Field);
}
}
class StoreStaticField(FieldReference field) : UnaryInstruction(OpCode.Stsfld), ISupportsVolatilePrefix
{
public readonly FieldReference Field = field;
public bool IsVolatile { get; set; }
public override bool NoResult { get { return true; } }
public override void WriteTo(ITextOutput output)
{
if (IsVolatile)
output.Write("volatile.");
output.Write(OpCode);
output.Write(' ');
Disassembler.DisassemblerHelpers.WriteOperand(output, Field);
output.Write('(');
Operand.WriteTo(output);
output.Write(')');
}
}
class LoadInstanceField(FieldReference field, OpCode opCode = OpCode.Ldfld) : UnaryInstruction(opCode), ISupportsVolatilePrefix
{
public readonly FieldReference Field = field;
public bool IsVolatile { get; set; }
public override void WriteTo(ITextOutput output)
{
if (IsVolatile)
output.Write("volatile.");
output.Write(OpCode);
output.Write(' ');
output.WriteReference(Field.Name, Field);
output.Write('(');
Operand.WriteTo(output);
output.Write(')');
}
}
class StoreInstanceField(FieldReference field, OpCode opCode = OpCode.Ldfld) : BinaryInstruction(opCode), ISupportsVolatilePrefix
{
public readonly FieldReference Field = field;
public bool IsVolatile { get; set; }
public override bool NoResult { get { return true; } }
public override void WriteTo(ITextOutput output)
{
if (IsVolatile)
output.Write("volatile.");
output.Write(OpCode);
output.Write(' ');
output.WriteReference(Field.Name, Field);
output.Write('(');
Left.WriteTo(output);
output.Write(", ");
Right.WriteTo(output);
output.Write(')');
}
}
}

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

@ -11,8 +11,8 @@ namespace ICSharpCode.Decompiler.IL @@ -11,8 +11,8 @@ namespace ICSharpCode.Decompiler.IL
/// </summary>
public abstract class ILInstruction(public readonly OpCode OpCode)
{
public static readonly ILInstruction Nop = new SimpleInstruction(OpCode.Nop);
public static readonly ILInstruction Pop = new SimpleInstruction(OpCode.Pop);
public static readonly ILInstruction Nop = new Nop();
public static readonly ILInstruction Pop = new Pop();
/// <summary>
/// Gets the ILRange for this instruction alone, ignoring the operands.
@ -26,6 +26,30 @@ namespace ICSharpCode.Decompiler.IL @@ -26,6 +26,30 @@ namespace ICSharpCode.Decompiler.IL
/// </summary>
public abstract bool IsPeeking { get; }
public abstract void WriteTo(ITextOutput output);
/// <summary>
/// Gets whether the instruction produces no result.
/// Instructions without result may not be used as arguments to other instructions;
/// and do not result in a stack push when used as a top-level instruction within a block.
/// </summary>
public virtual bool NoResult
{
get { return false; }
}
/// <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 virtual void WriteTo(ITextOutput output)
{
output.Write(OpCode);
}
public abstract void TransformChildren(Func<ILInstruction, ILInstruction> transformFunc);
}
}

66
ICSharpCode.Decompiler/IL/Instructions/OpCode.cs

@ -8,28 +8,26 @@ namespace ICSharpCode.Decompiler.IL @@ -8,28 +8,26 @@ namespace ICSharpCode.Decompiler.IL
{
public enum OpCode
{
/// <summary>
/// A instruction that could not be decoded correctly.
/// Invalid instructions may appear in unreachable code.
/// </summary>
Invalid,
/// <summary>
/// No operation. Takes 0 arguments and returns void.
/// <see cref="IL.Nop"/>
/// </summary>
Nop,
/// <summary>
/// Pops the top of the evaluation stack and returns the value.
/// Does not correspond to any IL instruction, but encodes the implicit stack use by the IL instruction.
/// <see cref="IL.Pop"/>
/// </summary>
Pop,
/// <summary>
/// Peeks at the top of the evaluation stack and returns the value.
/// Corresponds to IL 'dup'.
/// Corresponds to IL 'dup'. <see cref="IL.Peek"/>
/// </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.
/// <see cref="VoidInstruction"/>
/// </summary>
Void,
/// <summary>
@ -79,24 +77,24 @@ namespace ICSharpCode.Decompiler.IL @@ -79,24 +77,24 @@ namespace ICSharpCode.Decompiler.IL
/// </summary>
BitNot,
/// <summary>
/// Retrieves the RuntimeArgumentHandle
/// Retrieves the RuntimeArgumentHandle. <see cref="IL.Arglist"/>
/// </summary>
Arglist,
/// <summary>
/// <c>if (cond) goto target;</c>
/// <see cref="ConditionalBranchInstruction"/>
/// <see cref="IL.ConditionalBranch"/>
/// </summary>
ConditionalBranch,
/// <summary>
/// <c>goto target;</c>
/// <see cref="BranchInstruction"/>
/// <see cref="IL.Branch"/>
/// </summary>
Branch,
Leave,
/// <summary>
/// Breakpoint instruction.
/// </summary>
Break,
DebugBreak,
/// <summary>
/// Compare equal.
/// Returns 1 (of type I4) if two numbers or object references are equal; 0 otherwise.
@ -149,33 +147,33 @@ namespace ICSharpCode.Decompiler.IL @@ -149,33 +147,33 @@ namespace ICSharpCode.Decompiler.IL
Conv,
/// <summary>
/// Loads the value of a variable. (ldarg/ldloc)
/// <see cref="LoadVarInstruction"/>
/// <see cref="IL.LdLoc"/>
/// </summary>
LoadVar,
LdLoc,
/// <summary>
/// Loads the address of a variable as managed ref. (ldarga/ldloca)
/// <see cref="LoadVarInstruction"/>
/// Loads the address of a variable. (ldarga/ldloca)
/// <see cref="IL.LdLoca"/>
/// </summary>
LoadVarAddress,
LdLoca,
/// <summary>
/// Stores a value into a variable. (starg/stloc)
/// <see cref="StoreVarInstruction"/>
/// <see cref="IL.StLoc"/>
/// </summary>
StoreVar,
StLoc,
/// <summary>
/// Loads a constant string. <see cref="ConstantStringInstruction"/>
/// Loads a constant string. <see cref="ConstantString"/>
/// </summary>
LdStr,
/// <summary>
/// Loads a constant 32-bit integer. <see cref="ConstantI4Instruction"/>
/// Loads a constant 32-bit integer. <see cref="ConstantI4"/>
/// </summary>
LdcI4,
/// <summary>
/// Loads a constant 64-bit integer. <see cref="ConstantI8Instruction"/>
/// Loads a constant 64-bit integer. <see cref="ConstantI8"/>
/// </summary>
LdcI8,
/// <summary>
/// Loads a constant floating point number. <see cref="ConstantFloatInstruction"/>
/// Loads a constant floating point number. <see cref="ConstantFloat"/>
/// </summary>
LdcF,
/// <summary>
@ -184,7 +182,7 @@ namespace ICSharpCode.Decompiler.IL @@ -184,7 +182,7 @@ namespace ICSharpCode.Decompiler.IL
LdNull,
/// <summary>
/// Returns from the current method or lambda.
/// <see cref="UnaryInstruction"/> or <see cref="SimpleInstruction"/>, depending on whether
/// <see cref="IL.RetVoid"/> or <see cref="IL.Ret"/>, depending on whether
/// the method has return type void.
/// </summary>
Ret,
@ -196,5 +194,29 @@ namespace ICSharpCode.Decompiler.IL @@ -196,5 +194,29 @@ namespace ICSharpCode.Decompiler.IL
/// Shift right. <see cref="BinaryNumericInstruction"/>
/// </summary>
Shr,
/// <summary>
/// Load instance field. <see cref="LoadInstanceField"/>
/// </summary>
Ldfld,
/// <summary>
/// Load instance field address. <see cref="LoadInstanceField"/>
/// </summary>
Ldflda,
/// <summary>
/// Store to instance field. <see cref="StoreInstanceField"/>
/// </summary>
Stfld,
/// <summary>
/// Load static field. <see cref="LoadStaticField"/>
/// </summary>
Ldsfld,
/// <summary>
/// Load static field address. <see cref="LoadStaticField"/>
/// </summary>
Ldsflda,
/// <summary>
/// Store to static field. <see cref="StoreStaticField"/>
/// </summary>
Stsfld,
}
}

5
ICSharpCode.Decompiler/IL/Instructions/Prefix.cs

@ -6,13 +6,16 @@ using System.Threading.Tasks; @@ -6,13 +6,16 @@ using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.IL
{
interface ISupportsMemoryPrefix
interface ISupportsMemoryPrefix : ISupportsVolatilePrefix
{
/// <summary>
/// Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix.
/// </summary>
byte UnalignedPrefix { get; set; }
}
interface ISupportsVolatilePrefix
{
/// <summary>
/// Gets/Sets whether the memory access is volatile.
/// </summary>

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

@ -7,29 +7,47 @@ using System.Threading.Tasks; @@ -7,29 +7,47 @@ using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.IL
{
/// <summary>
/// A simple instruction that does not pop any elements from the stack.
/// A simple instruction that does not have any arguments.
/// </summary>
class SimpleInstruction(OpCode opCode) : ILInstruction(opCode)
abstract class SimpleInstruction(OpCode opCode) : ILInstruction(opCode)
{
public override bool IsPeeking { get { return false; } }
public override void WriteTo(ITextOutput output)
public override void TransformChildren(Func<ILInstruction, ILInstruction> transformFunc)
{
output.Write(OpCode);
}
}
class PeekInstruction(OpCode opCode = OpCode.Peek) : ILInstruction(opCode)
class Nop() : SimpleInstruction(OpCode.Nop)
{
public override bool NoResult { get { return true; } }
}
class Pop() : SimpleInstruction(OpCode.Pop)
{
}
class Peek() : SimpleInstruction(OpCode.Peek)
{
public override bool IsPeeking { get { return true; } }
}
public override void WriteTo(ITextOutput output)
{
output.Write(OpCode);
}
class Ckfinite() : SimpleInstruction(OpCode.Ckfinite)
{
public override bool IsPeeking { get { return true; } }
public override bool NoResult { get { return true; } }
}
class Arglist() : SimpleInstruction(OpCode.Arglist)
{
}
class ConstantStringInstruction(public readonly string Value) : SimpleInstruction(OpCode.LdStr)
class DebugBreak() : SimpleInstruction(OpCode.DebugBreak)
{
public override bool NoResult { get { return true; } }
}
class ConstantString(public readonly string Value) : SimpleInstruction(OpCode.LdStr)
{
public override void WriteTo(ITextOutput output)
{
@ -37,7 +55,7 @@ namespace ICSharpCode.Decompiler.IL @@ -37,7 +55,7 @@ namespace ICSharpCode.Decompiler.IL
}
}
class ConstantI4Instruction(public readonly int Value) : SimpleInstruction(OpCode.LdcI4)
class ConstantI4(public readonly int Value) : SimpleInstruction(OpCode.LdcI4)
{
public override void WriteTo(ITextOutput output)
{
@ -45,7 +63,7 @@ namespace ICSharpCode.Decompiler.IL @@ -45,7 +63,7 @@ namespace ICSharpCode.Decompiler.IL
}
}
class ConstantI8Instruction(public readonly long Value) : SimpleInstruction(OpCode.LdcI8)
class ConstantI8(public readonly long Value) : SimpleInstruction(OpCode.LdcI8)
{
public override void WriteTo(ITextOutput output)
{
@ -53,11 +71,15 @@ namespace ICSharpCode.Decompiler.IL @@ -53,11 +71,15 @@ namespace ICSharpCode.Decompiler.IL
}
}
class ConstantFloatInstruction(public readonly double Value) : SimpleInstruction(OpCode.LdcI8)
class ConstantFloat(public readonly double Value) : SimpleInstruction(OpCode.LdcI8)
{
public override void WriteTo(ITextOutput output)
{
Disassembler.DisassemblerHelpers.WriteOperand(output, Value);
}
}
class ConstantNull() : SimpleInstruction(OpCode.LdNull)
{
}
}

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

@ -6,11 +6,11 @@ using System.Threading.Tasks; @@ -6,11 +6,11 @@ using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.IL
{
class UnaryInstruction(OpCode opCode) : ILInstruction(opCode)
abstract class UnaryInstruction(OpCode opCode) : ILInstruction(opCode)
{
public ILInstruction Operand = Pop;
public override bool IsPeeking { get { return Operand.IsPeeking; } }
public sealed override bool IsPeeking { get { return Operand.IsPeeking; } }
public override void WriteTo(ITextOutput output)
{
@ -19,6 +19,16 @@ namespace ICSharpCode.Decompiler.IL @@ -19,6 +19,16 @@ namespace ICSharpCode.Decompiler.IL
Operand.WriteTo(output);
output.Write(')');
}
public override void TransformChildren(Func<ILInstruction, ILInstruction> transformFunc)
{
Operand = transformFunc(Operand);
}
}
class VoidInstruction() : UnaryInstruction(OpCode.Void)
{
public override bool NoResult { get { return true; } }
}
class LogicNotInstruction() : UnaryInstruction(OpCode.LogicNot)

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

@ -6,24 +6,25 @@ using System.Threading.Tasks; @@ -6,24 +6,25 @@ using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.IL
{
class LoadVarInstruction(public readonly ILVariable Variable, OpCode opCode = OpCode.LoadVar) : ILInstruction(opCode)
class LdLoc(public readonly ILVariable Variable) : SimpleInstruction(OpCode.LdLoc)
{
public override bool IsPeeking { get { return false; } }
public override void WriteTo(ITextOutput output)
{
if (OpCode != OpCode.LoadVar) {
output.Write(OpCode);
output.Write(' ');
}
output.WriteReference(Variable.ToString(), Variable, isLocal: true);
}
}
class StoreVarInstruction(public readonly ILVariable Variable) : UnaryInstruction(OpCode.StoreVar)
class LdLoca(public readonly ILVariable Variable) : SimpleInstruction(OpCode.LdLoca)
{
public override bool IsPeeking { get { return false; } }
public override void WriteTo(ITextOutput output)
{
output.Write("ref ");
output.WriteReference(Variable.ToString(), Variable, isLocal: true);
}
}
class StLoc(public readonly ILVariable Variable) : UnaryInstruction(OpCode.StLoc)
{
public override void WriteTo(ITextOutput output)
{
output.WriteReference(Variable.ToString(), Variable, isLocal: true);

Loading…
Cancel
Save