@ -60,14 +60,16 @@ namespace ICSharpCode.Decompiler.IL
@@ -60,14 +60,16 @@ namespace ICSharpCode.Decompiler.IL
Cil . MethodBody body ;
BlobReader reader ;
Stack < StackType > s tack;
Immutable Stack< ILVariable > currentS tack;
ILVariable [ ] parameterVariables ;
ILVariable [ ] localVariables ;
BitArray isBranchTarget ;
List < ILInstruction > instructionBuilder ;
// Dictionary that stores stacks for forward jumps
Dictionary < int , ImmutableArray < StackType > > branchStackDict ;
// Dictionary that stores stacks for each IL instruction
Dictionary < int , ImmutableStack < ILVariable > > stackByOffset ;
UnionFind < ILVariable > unionFind ;
IEnumerable < ILVariable > stackVariables ;
void Init ( Cil . MethodBody body )
{
@ -75,12 +77,13 @@ namespace ICSharpCode.Decompiler.IL
@@ -75,12 +77,13 @@ namespace ICSharpCode.Decompiler.IL
throw new ArgumentNullException ( "body" ) ;
this . body = body ;
this . reader = body . GetILReader ( ) ;
this . stack = new Stack < StackType > ( body . MaxStackSize ) ;
this . currentStack = ImmutableStack < ILVariable > . Empty ;
this . unionFind = new UnionFind < ILVariable > ( ) ;
InitParameterVariables ( ) ;
this . localVariables = body . Variables . SelectArray ( CreateILVariable ) ;
this . instructionBuilder = new List < ILInstruction > ( ) ;
this . isBranchTarget = new BitArray ( body . CodeSize ) ;
this . branchStackDic t = new Dictionary < int , ImmutableArray < StackTyp e > > ( ) ;
this . stackByOffse t = new Dictionary < int , ImmutableStack < ILVariabl e > > ( ) ;
}
IMetadataTokenProvider ReadAndDecodeMetadataToken ( )
@ -154,46 +157,69 @@ namespace ICSharpCode.Decompiler.IL
@@ -154,46 +157,69 @@ namespace ICSharpCode.Decompiler.IL
Debug . Fail ( message ) ;
}
void ReadInstructions ( Dictionary < int , ImmutableArray < StackType > > outputStacks , CancellationToken cancellationToken )
void MergeStacks ( ImmutableStack < ILVariable > a , ImmutableStack < ILVariable > b )
{
var enum1 = a . GetEnumerator ( ) ;
var enum2 = b . GetEnumerator ( ) ;
while ( enum1 . MoveNext ( ) & & enum2 . MoveNext ( ) ) {
unionFind . Merge ( enum1 . Current , enum2 . Current ) ;
}
}
void StoreStackForOffset ( int offset , ImmutableStack < ILVariable > stack )
{
ImmutableStack < ILVariable > existing ;
if ( stackByOffset . TryGetValue ( offset , out existing ) ) {
MergeStacks ( existing , stack ) ;
} else {
stackByOffset . Add ( offset , stack ) ;
}
}
void ReadInstructions ( CancellationToken cancellationToken )
{
// Fill isBranchTarget and branchStackDict based on exception handlers
foreach ( var eh in body . ExceptionHandlers ) {
ImmutableStack < ILVariable > ehStack = null ;
if ( eh . HandlerType = = Cil . ExceptionHandlerType . Catch | | eh . HandlerType = = Cil . ExceptionHandlerType . Filter ) {
ehStack = ImmutableStack . Create (
new ILVariable ( VariableKind . Exception , typeSystem . Resolve ( eh . CatchType ) , eh . HandlerStart . Offset )
) ;
} else {
ehStack = ImmutableStack < ILVariable > . Empty ;
}
if ( eh . FilterStart ! = null ) {
isBranchTarget [ eh . FilterStart . Offset ] = true ;
branchStackDict [ eh . FilterStart . Offset ] = ImmutableArray . Create ( eh . CatchType . GetStackType ( ) ) ;
StoreStackForOffset ( eh . FilterStart . Offset , ehStack ) ;
}
if ( eh . HandlerStart ! = null ) {
isBranchTarget [ eh . HandlerStart . Offset ] = true ;
if ( eh . HandlerType = = Cil . ExceptionHandlerType . Catch | | eh . HandlerType = = Cil . ExceptionHandlerType . Filter )
branchStackDict [ eh . HandlerStart . Offset ] = ImmutableArray . Create ( eh . CatchType . GetStackType ( ) ) ;
else
branchStackDict [ eh . HandlerStart . Offset ] = ImmutableArray < StackType > . Empty ;
StoreStackForOffset ( eh . HandlerStart . Offset , ehStack ) ;
}
}
while ( reader . Position < reader . Length ) {
cancellationToken . ThrowIfCancellationRequested ( ) ;
int start = reader . Position ;
if ( outputStacks ! = null )
outputStacks . Add ( start , stack . ToImmutableArray ( ) ) ;
StoreStackForOffset ( start , currentStack ) ;
ILInstruction decodedInstruction = DecodeInstruction ( ) ;
if ( decodedInstruction . ResultType = = StackType . Unknown )
Warn ( "Unknown result type (might be due to invalid IL)" ) ;
decodedInstruction . CheckInvariant ( ) ;
if ( decodedInstruction . ResultType ! = StackType . Void )
stack . Push ( decodedInstruction . ResultType ) ;
decodedInstruction . ILRange = new Interval ( start , reader . Position ) ;
instructionBuilder . Add ( decodedInstruction ) ;
if ( decodedInstruction . HasFlag ( InstructionFlags . EndPointUnreachable ) ) {
stack . Clear ( ) ;
ImmutableArray < StackType > stackFromBranch ;
if ( branchStackDict . TryGetValue ( reader . Position , out stackFromBranch ) ) {
for ( int i = stackFromBranch . Length - 1 ; i > = 0 ; i - - ) {
stack . Push ( stackFromBranch [ i ] ) ;
}
if ( ! stackByOffset . TryGetValue ( reader . Position , out currentStack ) ) {
currentStack = ImmutableStack < ILVariable > . Empty ;
}
}
}
var visitor = new CollectStackVariablesVisitor ( unionFind ) ;
for ( int i = 0 ; i < instructionBuilder . Count ; i + + ) {
instructionBuilder [ i ] = instructionBuilder [ i ] . AcceptVisitor ( visitor ) ;
}
stackVariables = visitor . variables ;
}
/// <summary>
@ -202,17 +228,16 @@ namespace ICSharpCode.Decompiler.IL
@@ -202,17 +228,16 @@ namespace ICSharpCode.Decompiler.IL
public void WriteTypedIL ( Cil . MethodBody body , ITextOutput output , CancellationToken cancellationToken = default ( CancellationToken ) )
{
Init ( body ) ;
var outputStacks = new Dictionary < int , ImmutableArray < StackType > > ( ) ;
ReadInstructions ( outputStacks , cancellationToken ) ;
ReadInstructions ( cancellationToken ) ;
foreach ( var inst in instructionBuilder ) {
output . Write ( " [" ) ;
bool isFirstElement = true ;
foreach ( var element in outputStacks [ inst . ILRange . Start ] ) {
foreach ( var element in stackByOffset [ inst . ILRange . Start ] ) {
if ( isFirstElement )
isFirstElement = false ;
else
output . Write ( ", " ) ;
output . Write ( element ) ;
output . Write ( element . StackType ) ;
}
output . Write ( ']' ) ;
output . WriteLine ( ) ;
@ -234,25 +259,26 @@ namespace ICSharpCode.Decompiler.IL
@@ -234,25 +259,26 @@ namespace ICSharpCode.Decompiler.IL
public ILFunction ReadIL ( Cil . MethodBody body , CancellationToken cancellationToken = default ( CancellationToken ) )
{
Init ( body ) ;
ReadInstructions ( null , cancellationToken ) ;
ReadInstructions ( cancellationToken ) ;
var container = new BlockBuilder ( body , typeSystem ) . CreateBlocks ( instructionBuilder , isBranchTarget ) ;
var function = new ILFunction ( body . Method , container ) ;
function . Variables . AddRange ( parameterVariables ) ;
function . Variables . AddRange ( localVariables ) ;
function . Variables . AddRange ( stackVariables ) ;
function . AddRef ( ) ; // mark the root node
return function ;
}
ILInstruction Neg ( )
{
switch ( stack . PeekOrDefault ( ) ) {
switch ( PeekStackType ( ) ) {
case StackType . I4 :
case StackType . I :
return new Sub ( new LdcI4 ( 0 ) , Pop ( ) , checkForOverflow : false , sign : Sign . None ) ;
return Push ( new Sub ( new LdcI4 ( 0 ) , Pop ( ) , checkForOverflow : false , sign : Sign . None ) ) ;
case StackType . I8 :
return new Sub ( new LdcI8 ( 0 ) , Pop ( ) , checkForOverflow : false , sign : Sign . None ) ;
return Push ( new Sub ( new LdcI8 ( 0 ) , Pop ( ) , checkForOverflow : false , sign : Sign . None ) ) ;
case StackType . F :
return new Sub ( new LdcF ( 0 ) , Pop ( ) , checkForOverflow : false , sign : Sign . None ) ;
return Push ( new Sub ( new LdcF ( 0 ) , Pop ( ) , checkForOverflow : false , sign : Sign . None ) ) ;
default :
Warn ( "Unsupported input type for neg: " ) ;
goto case StackType . I4 ;
@ -282,7 +308,7 @@ namespace ICSharpCode.Decompiler.IL
@@ -282,7 +308,7 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode . And :
return BinaryNumeric ( OpCode . BitAnd ) ;
case ILOpCode . Arglist :
return new Arglist ( ) ;
return Push ( new Arglist ( ) ) ;
case ILOpCode . Beq :
return DecodeComparisonBranch ( false , OpCode . Ceq , OpCode . Ceq , false ) ;
case ILOpCode . Beq_S :
@ -344,83 +370,83 @@ namespace ICSharpCode.Decompiler.IL
@@ -344,83 +370,83 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode . Calli :
throw new NotImplementedException ( ) ;
case ILOpCode . Ceq :
return Comparison ( OpCode . Ceq , OpCode . Ceq ) ;
return Push ( Comparison ( OpCode . Ceq , OpCode . Ceq ) ) ;
case ILOpCode . Cgt :
return Comparison ( OpCode . Cgt , OpCode . Cgt ) ;
return Push ( Comparison ( OpCode . Cgt , OpCode . Cgt ) ) ;
case ILOpCode . Cgt_Un :
return Comparison ( OpCode . Cgt_Un , OpCode . Cgt_Un ) ;
return Push ( Comparison ( OpCode . Cgt_Un , OpCode . Cgt_Un ) ) ;
case ILOpCode . Clt :
return Comparison ( OpCode . Clt , OpCode . Clt ) ;
return Push ( Comparison ( OpCode . Clt , OpCode . Clt ) ) ;
case ILOpCode . Clt_Un :
return Comparison ( OpCode . Clt_Un , OpCode . Clt_Un ) ;
return Push ( Comparison ( OpCode . Clt_Un , OpCode . Clt_Un ) ) ;
case ILOpCode . Ckfinite :
return new Ckfinite ( new Peek ( stack . Count > 0 ? stack . Peek ( ) : StackType . Unknown ) ) ;
return new Ckfinite ( Peek ( ) ) ;
case ILOpCode . Conv_I1 :
return new Conv ( Pop ( ) , PrimitiveType . I1 , false , Sign . None ) ;
return Push ( new Conv ( Pop ( ) , PrimitiveType . I1 , false , Sign . None ) ) ;
case ILOpCode . Conv_I2 :
return new Conv ( Pop ( ) , PrimitiveType . I2 , false , Sign . None ) ;
return Push ( new Conv ( Pop ( ) , PrimitiveType . I2 , false , Sign . None ) ) ;
case ILOpCode . Conv_I4 :
return new Conv ( Pop ( ) , PrimitiveType . I4 , false , Sign . None ) ;
return Push ( new Conv ( Pop ( ) , PrimitiveType . I4 , false , Sign . None ) ) ;
case ILOpCode . Conv_I8 :
return new Conv ( Pop ( ) , PrimitiveType . I8 , false , Sign . None ) ;
return Push ( new Conv ( Pop ( ) , PrimitiveType . I8 , false , Sign . None ) ) ;
case ILOpCode . Conv_R4 :
return new Conv ( Pop ( ) , PrimitiveType . R4 , false , Sign . Signed ) ;
return Push ( new Conv ( Pop ( ) , PrimitiveType . R4 , false , Sign . Signed ) ) ;
case ILOpCode . Conv_R8 :
return new Conv ( Pop ( ) , PrimitiveType . R8 , false , Sign . Signed ) ;
return Push ( new Conv ( Pop ( ) , PrimitiveType . R8 , false , Sign . Signed ) ) ;
case ILOpCode . Conv_U1 :
return new Conv ( Pop ( ) , PrimitiveType . U1 , false , Sign . None ) ;
return Push ( new Conv ( Pop ( ) , PrimitiveType . U1 , false , Sign . None ) ) ;
case ILOpCode . Conv_U2 :
return new Conv ( Pop ( ) , PrimitiveType . U2 , false , Sign . None ) ;
return Push ( new Conv ( Pop ( ) , PrimitiveType . U2 , false , Sign . None ) ) ;
case ILOpCode . Conv_U4 :
return new Conv ( Pop ( ) , PrimitiveType . U4 , false , Sign . None ) ;
return Push ( new Conv ( Pop ( ) , PrimitiveType . U4 , false , Sign . None ) ) ;
case ILOpCode . Conv_U8 :
return new Conv ( Pop ( ) , PrimitiveType . U8 , false , Sign . None ) ;
return Push ( new Conv ( Pop ( ) , PrimitiveType . U8 , false , Sign . None ) ) ;
case ILOpCode . Conv_I :
return new Conv ( Pop ( ) , PrimitiveType . I , false , Sign . None ) ;
return Push ( new Conv ( Pop ( ) , PrimitiveType . I , false , Sign . None ) ) ;
case ILOpCode . Conv_U :
return new Conv ( Pop ( ) , PrimitiveType . U , false , Sign . None ) ;
return Push ( new Conv ( Pop ( ) , PrimitiveType . U , false , Sign . None ) ) ;
case ILOpCode . Conv_R_Un :
return new Conv ( Pop ( ) , PrimitiveType . R8 , false , Sign . Unsigned ) ;
return Push ( new Conv ( Pop ( ) , PrimitiveType . R8 , false , Sign . Unsigned ) ) ;
case ILOpCode . Conv_Ovf_I1 :
return new Conv ( Pop ( ) , PrimitiveType . I1 , true , Sign . Signed ) ;
return Push ( new Conv ( Pop ( ) , PrimitiveType . I1 , true , Sign . Signed ) ) ;
case ILOpCode . Conv_Ovf_I2 :
return new Conv ( Pop ( ) , PrimitiveType . I2 , true , Sign . Signed ) ;
return Push ( new Conv ( Pop ( ) , PrimitiveType . I2 , true , Sign . Signed ) ) ;
case ILOpCode . Conv_Ovf_I4 :
return new Conv ( Pop ( ) , PrimitiveType . I4 , true , Sign . Signed ) ;
return Push ( new Conv ( Pop ( ) , PrimitiveType . I4 , true , Sign . Signed ) ) ;
case ILOpCode . Conv_Ovf_I8 :
return new Conv ( Pop ( ) , PrimitiveType . I8 , true , Sign . Signed ) ;
return Push ( new Conv ( Pop ( ) , PrimitiveType . I8 , true , Sign . Signed ) ) ;
case ILOpCode . Conv_Ovf_U1 :
return new Conv ( Pop ( ) , PrimitiveType . U1 , true , Sign . Signed ) ;
return Push ( new Conv ( Pop ( ) , PrimitiveType . U1 , true , Sign . Signed ) ) ;
case ILOpCode . Conv_Ovf_U2 :
return new Conv ( Pop ( ) , PrimitiveType . U2 , true , Sign . Signed ) ;
return Push ( new Conv ( Pop ( ) , PrimitiveType . U2 , true , Sign . Signed ) ) ;
case ILOpCode . Conv_Ovf_U4 :
return new Conv ( Pop ( ) , PrimitiveType . U4 , true , Sign . Signed ) ;
return Push ( new Conv ( Pop ( ) , PrimitiveType . U4 , true , Sign . Signed ) ) ;
case ILOpCode . Conv_Ovf_U8 :
return new Conv ( Pop ( ) , PrimitiveType . U8 , true , Sign . Signed ) ;
return Push ( new Conv ( Pop ( ) , PrimitiveType . U8 , true , Sign . Signed ) ) ;
case ILOpCode . Conv_Ovf_I :
return new Conv ( Pop ( ) , PrimitiveType . I , true , Sign . Signed ) ;
return Push ( new Conv ( Pop ( ) , PrimitiveType . I , true , Sign . Signed ) ) ;
case ILOpCode . Conv_Ovf_U :
return new Conv ( Pop ( ) , PrimitiveType . U , true , Sign . Signed ) ;
return Push ( new Conv ( Pop ( ) , PrimitiveType . U , true , Sign . Signed ) ) ;
case ILOpCode . Conv_Ovf_I1_Un :
return new Conv ( Pop ( ) , PrimitiveType . I1 , true , Sign . Unsigned ) ;
return Push ( new Conv ( Pop ( ) , PrimitiveType . I1 , true , Sign . Unsigned ) ) ;
case ILOpCode . Conv_Ovf_I2_Un :
return new Conv ( Pop ( ) , PrimitiveType . I2 , true , Sign . Unsigned ) ;
return Push ( new Conv ( Pop ( ) , PrimitiveType . I2 , true , Sign . Unsigned ) ) ;
case ILOpCode . Conv_Ovf_I4_Un :
return new Conv ( Pop ( ) , PrimitiveType . I4 , true , Sign . Unsigned ) ;
return Push ( new Conv ( Pop ( ) , PrimitiveType . I4 , true , Sign . Unsigned ) ) ;
case ILOpCode . Conv_Ovf_I8_Un :
return new Conv ( Pop ( ) , PrimitiveType . I8 , true , Sign . Unsigned ) ;
return Push ( new Conv ( Pop ( ) , PrimitiveType . I8 , true , Sign . Unsigned ) ) ;
case ILOpCode . Conv_Ovf_U1_Un :
return new Conv ( Pop ( ) , PrimitiveType . U1 , true , Sign . Unsigned ) ;
return Push ( new Conv ( Pop ( ) , PrimitiveType . U1 , true , Sign . Unsigned ) ) ;
case ILOpCode . Conv_Ovf_U2_Un :
return new Conv ( Pop ( ) , PrimitiveType . U2 , true , Sign . Unsigned ) ;
return Push ( new Conv ( Pop ( ) , PrimitiveType . U2 , true , Sign . Unsigned ) ) ;
case ILOpCode . Conv_Ovf_U4_Un :
return new Conv ( Pop ( ) , PrimitiveType . U4 , true , Sign . Unsigned ) ;
return Push ( new Conv ( Pop ( ) , PrimitiveType . U4 , true , Sign . Unsigned ) ) ;
case ILOpCode . Conv_Ovf_U8_Un :
return new Conv ( Pop ( ) , PrimitiveType . U8 , true , Sign . Unsigned ) ;
return Push ( new Conv ( Pop ( ) , PrimitiveType . U8 , true , Sign . Unsigned ) ) ;
case ILOpCode . Conv_Ovf_I_Un :
return new Conv ( Pop ( ) , PrimitiveType . I , true , Sign . Unsigned ) ;
return Push ( new Conv ( Pop ( ) , PrimitiveType . I , true , Sign . Unsigned ) ) ;
case ILOpCode . Conv_Ovf_U_Un :
return new Conv ( Pop ( ) , PrimitiveType . U , true , Sign . Unsigned ) ;
return Push ( new Conv ( Pop ( ) , PrimitiveType . U , true , Sign . Unsigned ) ) ;
case ILOpCode . Cpblk :
throw new NotImplementedException ( ) ;
case ILOpCode . Div :
@ -428,7 +454,7 @@ namespace ICSharpCode.Decompiler.IL
@@ -428,7 +454,7 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode . Div_Un :
return BinaryNumeric ( OpCode . Div , false , Sign . Unsigned ) ;
case ILOpCode . Dup :
return new Peek ( stack . Count > 0 ? stack . Peek ( ) : StackType . Unknown ) ;
return Push ( Peek ( ) ) ;
case ILOpCode . Endfilter :
case ILOpCode . Endfinally :
return new Leave ( null ) ;
@ -437,26 +463,26 @@ namespace ICSharpCode.Decompiler.IL
@@ -437,26 +463,26 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode . Jmp :
throw new NotImplementedException ( ) ;
case ILOpCode . Ldarg :
return Ldarg ( reader . ReadUInt16 ( ) ) ;
return Push ( Ldarg ( reader . ReadUInt16 ( ) ) ) ;
case ILOpCode . Ldarg_S :
return Ldarg ( reader . ReadByte ( ) ) ;
return Push ( Ldarg ( reader . ReadByte ( ) ) ) ;
case ILOpCode . Ldarg_0 :
case ILOpCode . Ldarg_1 :
case ILOpCode . Ldarg_2 :
case ILOpCode . Ldarg_3 :
return Ldarg ( ilOpCode - ILOpCode . Ldarg_0 ) ;
return Push ( Ldarg ( ilOpCode - ILOpCode . Ldarg_0 ) ) ;
case ILOpCode . Ldarga :
return Ldarga ( reader . ReadUInt16 ( ) ) ;
return Push ( Ldarga ( reader . ReadUInt16 ( ) ) ) ;
case ILOpCode . Ldarga_S :
return Ldarga ( reader . ReadByte ( ) ) ;
return Push ( Ldarga ( reader . ReadByte ( ) ) ) ;
case ILOpCode . Ldc_I4 :
return new LdcI4 ( reader . ReadInt32 ( ) ) ;
return Push ( new LdcI4 ( reader . ReadInt32 ( ) ) ) ;
case ILOpCode . Ldc_I8 :
return new LdcI8 ( reader . ReadInt64 ( ) ) ;
return Push ( new LdcI8 ( reader . ReadInt64 ( ) ) ) ;
case ILOpCode . Ldc_R4 :
return new LdcF ( reader . ReadSingle ( ) ) ;
return Push ( new LdcF ( reader . ReadSingle ( ) ) ) ;
case ILOpCode . Ldc_R8 :
return new LdcF ( reader . ReadDouble ( ) ) ;
return Push ( new LdcF ( reader . ReadDouble ( ) ) ) ;
case ILOpCode . Ldc_I4_M1 :
case ILOpCode . Ldc_I4_0 :
case ILOpCode . Ldc_I4_1 :
@ -467,56 +493,56 @@ namespace ICSharpCode.Decompiler.IL
@@ -467,56 +493,56 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode . Ldc_I4_6 :
case ILOpCode . Ldc_I4_7 :
case ILOpCode . Ldc_I4_8 :
return new LdcI4 ( ( int ) ilOpCode - ( int ) ILOpCode . Ldc_I4_0 ) ;
return Push ( new LdcI4 ( ( int ) ilOpCode - ( int ) ILOpCode . Ldc_I4_0 ) ) ;
case ILOpCode . Ldc_I4_S :
return new LdcI4 ( reader . ReadSByte ( ) ) ;
return Push ( new LdcI4 ( reader . ReadSByte ( ) ) ) ;
case ILOpCode . Ldnull :
return new LdNull ( ) ;
return Push ( new LdNull ( ) ) ;
case ILOpCode . Ldstr :
return DecodeLdstr ( ) ;
return Push ( DecodeLdstr ( ) ) ;
case ILOpCode . Ldftn :
return new LdFtn ( ReadAndDecodeMethodReference ( ) ) ;
return Push ( new LdFtn ( ReadAndDecodeMethodReference ( ) ) ) ;
case ILOpCode . Ldind_I1 :
return new LdObj ( Pop ( ) , compilation . FindType ( KnownTypeCode . SByte ) ) ;
return Push ( new LdObj ( Pop ( ) , compilation . FindType ( KnownTypeCode . SByte ) ) ) ;
case ILOpCode . Ldind_I2 :
return new LdObj ( Pop ( ) , compilation . FindType ( KnownTypeCode . Int16 ) ) ;
return Push ( new LdObj ( Pop ( ) , compilation . FindType ( KnownTypeCode . Int16 ) ) ) ;
case ILOpCode . Ldind_I4 :
return new LdObj ( Pop ( ) , compilation . FindType ( KnownTypeCode . Int32 ) ) ;
return Push ( new LdObj ( Pop ( ) , compilation . FindType ( KnownTypeCode . Int32 ) ) ) ;
case ILOpCode . Ldind_I8 :
return new LdObj ( Pop ( ) , compilation . FindType ( KnownTypeCode . Int64 ) ) ;
return Push ( new LdObj ( Pop ( ) , compilation . FindType ( KnownTypeCode . Int64 ) ) ) ;
case ILOpCode . Ldind_U1 :
return new LdObj ( Pop ( ) , compilation . FindType ( KnownTypeCode . Byte ) ) ;
return Push ( new LdObj ( Pop ( ) , compilation . FindType ( KnownTypeCode . Byte ) ) ) ;
case ILOpCode . Ldind_U2 :
return new LdObj ( Pop ( ) , compilation . FindType ( KnownTypeCode . UInt16 ) ) ;
return Push ( new LdObj ( Pop ( ) , compilation . FindType ( KnownTypeCode . UInt16 ) ) ) ;
case ILOpCode . Ldind_U4 :
return new LdObj ( Pop ( ) , compilation . FindType ( KnownTypeCode . UInt32 ) ) ;
return Push ( new LdObj ( Pop ( ) , compilation . FindType ( KnownTypeCode . UInt32 ) ) ) ;
case ILOpCode . Ldind_R4 :
return new LdObj ( Pop ( ) , compilation . FindType ( KnownTypeCode . Single ) ) ;
return Push ( new LdObj ( Pop ( ) , compilation . FindType ( KnownTypeCode . Single ) ) ) ;
case ILOpCode . Ldind_R8 :
return new LdObj ( Pop ( ) , compilation . FindType ( KnownTypeCode . Double ) ) ;
return Push ( new LdObj ( Pop ( ) , compilation . FindType ( KnownTypeCode . Double ) ) ) ;
case ILOpCode . Ldind_I :
return new LdObj ( Pop ( ) , compilation . FindType ( KnownTypeCode . IntPtr ) ) ;
return Push ( new LdObj ( Pop ( ) , compilation . FindType ( KnownTypeCode . IntPtr ) ) ) ;
case ILOpCode . Ldind_Ref :
return new LdObj ( Pop ( ) , compilation . FindType ( KnownTypeCode . Object ) ) ;
return Push ( new LdObj ( Pop ( ) , compilation . FindType ( KnownTypeCode . Object ) ) ) ;
case ILOpCode . Ldloc :
return Ldloc ( reader . ReadUInt16 ( ) ) ;
return Push ( Ldloc ( reader . ReadUInt16 ( ) ) ) ;
case ILOpCode . Ldloc_S :
return Ldloc ( reader . ReadByte ( ) ) ;
return Push ( Ldloc ( reader . ReadByte ( ) ) ) ;
case ILOpCode . Ldloc_0 :
case ILOpCode . Ldloc_1 :
case ILOpCode . Ldloc_2 :
case ILOpCode . Ldloc_3 :
return Ldloc ( ilOpCode - ILOpCode . Ldloc_0 ) ;
return Push ( Ldloc ( ilOpCode - ILOpCode . Ldloc_0 ) ) ;
case ILOpCode . Ldloca :
return Ldloca ( reader . ReadUInt16 ( ) ) ;
return Push ( Ldloca ( reader . ReadUInt16 ( ) ) ) ;
case ILOpCode . Ldloca_S :
return Ldloca ( reader . ReadByte ( ) ) ;
return Push ( Ldloca ( reader . ReadByte ( ) ) ) ;
case ILOpCode . Leave :
return DecodeUnconditionalBranch ( false , isLeave : true ) ;
case ILOpCode . Leave_S :
return DecodeUnconditionalBranch ( true , isLeave : true ) ;
case ILOpCode . Localloc :
return new LocAlloc ( Pop ( ) ) ;
return Push ( new LocAlloc ( Pop ( ) ) ) ;
case ILOpCode . Mul :
return BinaryNumeric ( OpCode . Mul , false , Sign . None ) ;
case ILOpCode . Mul_Ovf :
@ -530,11 +556,11 @@ namespace ICSharpCode.Decompiler.IL
@@ -530,11 +556,11 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode . Nop :
return new Nop ( ) ;
case ILOpCode . Not :
return new BitNot ( Pop ( ) ) ;
return Push ( new BitNot ( Pop ( ) ) ) ;
case ILOpCode . Or :
return BinaryNumeric ( OpCode . BitOr ) ;
case ILOpCode . Pop :
return new Void ( Pop ( ) ) ;
return new Nop ( ) ;
case ILOpCode . Rem :
return BinaryNumeric ( OpCode . Rem , false , Sign . Signed ) ;
case ILOpCode . Rem_Un :
@ -552,21 +578,21 @@ namespace ICSharpCode.Decompiler.IL
@@ -552,21 +578,21 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode . Starg_S :
return Starg ( reader . ReadByte ( ) ) ;
case ILOpCode . Stind_I1 :
return new Void ( new StObj ( value : Pop ( ) , target : Pop ( ) , type : compilation . FindType ( KnownTypeCode . SByte ) ) ) ;
return new StObj ( value : Pop ( ) , target : Pop ( ) , type : compilation . FindType ( KnownTypeCode . SByte ) ) ;
case ILOpCode . Stind_I2 :
return new Void ( new StObj ( value : Pop ( ) , target : Pop ( ) , type : compilation . FindType ( KnownTypeCode . Int16 ) ) ) ;
return new StObj ( value : Pop ( ) , target : Pop ( ) , type : compilation . FindType ( KnownTypeCode . Int16 ) ) ;
case ILOpCode . Stind_I4 :
return new Void ( new StObj ( value : Pop ( ) , target : Pop ( ) , type : compilation . FindType ( KnownTypeCode . Int32 ) ) ) ;
return new StObj ( value : Pop ( ) , target : Pop ( ) , type : compilation . FindType ( KnownTypeCode . Int32 ) ) ;
case ILOpCode . Stind_I8 :
return new Void ( new StObj ( value : Pop ( ) , target : Pop ( ) , type : compilation . FindType ( KnownTypeCode . Int64 ) ) ) ;
return new StObj ( value : Pop ( ) , target : Pop ( ) , type : compilation . FindType ( KnownTypeCode . Int64 ) ) ;
case ILOpCode . Stind_R4 :
return new Void ( new StObj ( value : Pop ( ) , target : Pop ( ) , type : compilation . FindType ( KnownTypeCode . Single ) ) ) ;
return new StObj ( value : Pop ( ) , target : Pop ( ) , type : compilation . FindType ( KnownTypeCode . Single ) ) ;
case ILOpCode . Stind_R8 :
return new Void ( new StObj ( value : Pop ( ) , target : Pop ( ) , type : compilation . FindType ( KnownTypeCode . Double ) ) ) ;
return new StObj ( value : Pop ( ) , target : Pop ( ) , type : compilation . FindType ( KnownTypeCode . Double ) ) ;
case ILOpCode . Stind_I :
return new Void ( new StObj ( value : Pop ( ) , target : Pop ( ) , type : compilation . FindType ( KnownTypeCode . IntPtr ) ) ) ;
return new StObj ( value : Pop ( ) , target : Pop ( ) , type : compilation . FindType ( KnownTypeCode . IntPtr ) ) ;
case ILOpCode . Stind_Ref :
return new Void ( new StObj ( value : Pop ( ) , target : Pop ( ) , type : compilation . FindType ( KnownTypeCode . Object ) ) ) ;
return new StObj ( value : Pop ( ) , target : Pop ( ) , type : compilation . FindType ( KnownTypeCode . Object ) ) ;
case ILOpCode . Stloc :
return Stloc ( reader . ReadUInt16 ( ) ) ;
case ILOpCode . Stloc_S :
@ -587,61 +613,61 @@ namespace ICSharpCode.Decompiler.IL
@@ -587,61 +613,61 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode . Xor :
return BinaryNumeric ( OpCode . BitXor ) ;
case ILOpCode . Box :
return new Box ( Pop ( ) , ReadAndDecodeTypeReference ( ) ) ;
return Push ( new Box ( Pop ( ) , ReadAndDecodeTypeReference ( ) ) ) ;
case ILOpCode . Castclass :
return new CastClass ( Pop ( ) , ReadAndDecodeTypeReference ( ) ) ;
return Push ( new CastClass ( Pop ( ) , ReadAndDecodeTypeReference ( ) ) ) ;
case ILOpCode . Cpobj :
{
var type = ReadAndDecodeTypeReference ( ) ;
var ld = new LdObj ( Pop ( ) , type ) ;
return new Void ( new StObj ( Pop ( ) , ld , type ) ) ;
return new StObj ( Pop ( ) , ld , type ) ;
}
case ILOpCode . Initobj :
return InitObj ( Pop ( ) , ReadAndDecodeTypeReference ( ) ) ;
return Push ( InitObj ( Pop ( ) , ReadAndDecodeTypeReference ( ) ) ) ;
case ILOpCode . Isinst :
return new IsInst ( Pop ( ) , ReadAndDecodeTypeReference ( ) ) ;
return Push ( new IsInst ( Pop ( ) , ReadAndDecodeTypeReference ( ) ) ) ;
case ILOpCode . Ldelem :
return LdElem ( index : Pop ( ) , array : Pop ( ) , type : ReadAndDecodeTypeReference ( ) ) ;
return LdElem ( ReadAndDecodeTypeReference ( ) ) ;
case ILOpCode . Ldelem_I1 :
return LdElem ( index : Pop ( ) , array : Pop ( ) , type : compilation . FindType ( KnownTypeCode . SByte ) ) ;
return LdElem ( compilation . FindType ( KnownTypeCode . SByte ) ) ;
case ILOpCode . Ldelem_I2 :
return LdElem ( index : Pop ( ) , array : Pop ( ) , type : compilation . FindType ( KnownTypeCode . Int16 ) ) ;
return LdElem ( compilation . FindType ( KnownTypeCode . Int16 ) ) ;
case ILOpCode . Ldelem_I4 :
return LdElem ( index : Pop ( ) , array : Pop ( ) , type : compilation . FindType ( KnownTypeCode . Int32 ) ) ;
return LdElem ( compilation . FindType ( KnownTypeCode . Int32 ) ) ;
case ILOpCode . Ldelem_I8 :
return LdElem ( index : Pop ( ) , array : Pop ( ) , type : compilation . FindType ( KnownTypeCode . Int64 ) ) ;
return LdElem ( compilation . FindType ( KnownTypeCode . Int64 ) ) ;
case ILOpCode . Ldelem_U1 :
return LdElem ( index : Pop ( ) , array : Pop ( ) , type : compilation . FindType ( KnownTypeCode . Byte ) ) ;
return LdElem ( compilation . FindType ( KnownTypeCode . Byte ) ) ;
case ILOpCode . Ldelem_U2 :
return LdElem ( index : Pop ( ) , array : Pop ( ) , type : compilation . FindType ( KnownTypeCode . UInt16 ) ) ;
return LdElem ( compilation . FindType ( KnownTypeCode . UInt16 ) ) ;
case ILOpCode . Ldelem_U4 :
return LdElem ( index : Pop ( ) , array : Pop ( ) , type : compilation . FindType ( KnownTypeCode . UInt32 ) ) ;
return LdElem ( compilation . FindType ( KnownTypeCode . UInt32 ) ) ;
case ILOpCode . Ldelem_R4 :
return LdElem ( index : Pop ( ) , array : Pop ( ) , type : compilation . FindType ( KnownTypeCode . Single ) ) ;
return LdElem ( compilation . FindType ( KnownTypeCode . Single ) ) ;
case ILOpCode . Ldelem_R8 :
return LdElem ( index : Pop ( ) , array : Pop ( ) , type : compilation . FindType ( KnownTypeCode . Double ) ) ;
return LdElem ( compilation . FindType ( KnownTypeCode . Double ) ) ;
case ILOpCode . Ldelem_I :
return LdElem ( index : Pop ( ) , array : Pop ( ) , type : compilation . FindType ( KnownTypeCode . IntPtr ) ) ;
return LdElem ( compilation . FindType ( KnownTypeCode . IntPtr ) ) ;
case ILOpCode . Ldelem_Ref :
return LdElem ( index : Pop ( ) , array : Pop ( ) , type : compilation . FindType ( KnownTypeCode . Object ) ) ;
return LdElem ( compilation . FindType ( KnownTypeCode . Object ) ) ;
case ILOpCode . Ldelema :
return new LdElema ( index : Pop ( ) , array : Pop ( ) , type : ReadAndDecodeTypeReference ( ) ) ;
return Push ( new LdElema ( index : Pop ( ) , array : Pop ( ) , type : ReadAndDecodeTypeReference ( ) ) ) ;
case ILOpCode . Ldfld :
return new LdFld ( Pop ( ) , ReadAndDecodeFieldReference ( ) ) ;
return Push ( new LdFld ( Pop ( ) , ReadAndDecodeFieldReference ( ) ) ) ;
case ILOpCode . Ldflda :
return new LdFlda ( Pop ( ) , ReadAndDecodeFieldReference ( ) ) ;
return Push ( new LdFlda ( Pop ( ) , ReadAndDecodeFieldReference ( ) ) ) ;
case ILOpCode . Stfld :
return new Void ( new StFld ( value : Pop ( ) , target : Pop ( ) , field : ReadAndDecodeFieldReference ( ) ) ) ;
return new StFld ( value : Pop ( ) , target : Pop ( ) , field : ReadAndDecodeFieldReference ( ) ) ;
case ILOpCode . Ldlen :
return new LdLen ( Pop ( ) ) ;
return Push ( new LdLen ( Pop ( ) ) ) ;
case ILOpCode . Ldobj :
return new LdObj ( Pop ( ) , ReadAndDecodeTypeReference ( ) ) ;
return Push ( new LdObj ( Pop ( ) , ReadAndDecodeTypeReference ( ) ) ) ;
case ILOpCode . Ldsfld :
return new LdsFld ( ReadAndDecodeFieldReference ( ) ) ;
return Push ( new LdsFld ( ReadAndDecodeFieldReference ( ) ) ) ;
case ILOpCode . Ldsflda :
return new LdsFlda ( ReadAndDecodeFieldReference ( ) ) ;
return Push ( new LdsFlda ( ReadAndDecodeFieldReference ( ) ) ) ;
case ILOpCode . Stsfld :
return new Void ( new StsFld ( Pop ( ) , ReadAndDecodeFieldReference ( ) ) ) ;
return new StsFld ( Pop ( ) , ReadAndDecodeFieldReference ( ) ) ;
case ILOpCode . Ldtoken :
var memberReference = ReadAndDecodeMetadataToken ( ) as MemberReference ;
if ( memberReference is TypeReference )
@ -652,11 +678,11 @@ namespace ICSharpCode.Decompiler.IL
@@ -652,11 +678,11 @@ namespace ICSharpCode.Decompiler.IL
return new LdMemberToken ( typeSystem . Resolve ( ( MethodReference ) memberReference ) ) ;
throw new NotImplementedException ( ) ;
case ILOpCode . Ldvirtftn :
return new LdVirtFtn ( Pop ( ) , ReadAndDecodeMethodReference ( ) ) ;
return Push ( new LdVirtFtn ( Pop ( ) , ReadAndDecodeMethodReference ( ) ) ) ;
case ILOpCode . Mkrefany :
throw new NotImplementedException ( ) ;
case ILOpCode . Newarr :
return new NewArr ( ReadAndDecodeTypeReference ( ) , Pop ( ) ) ;
return Push ( new NewArr ( ReadAndDecodeTypeReference ( ) , Pop ( ) ) ) ;
case ILOpCode . Refanytype :
throw new NotImplementedException ( ) ;
case ILOpCode . Refanyval :
@ -666,46 +692,113 @@ namespace ICSharpCode.Decompiler.IL
@@ -666,46 +692,113 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode . Sizeof :
return new SizeOf ( ReadAndDecodeTypeReference ( ) ) ;
case ILOpCode . Stelem :
return StElem ( value : Pop ( ) , index : Pop ( ) , array : Pop ( ) , type : ReadAndDecodeTypeReference ( ) ) ;
return StElem ( ReadAndDecodeTypeReference ( ) ) ;
case ILOpCode . Stelem_I1 :
return StElem ( value : Pop ( ) , index : Pop ( ) , array : Pop ( ) , type : compilation . FindType ( KnownTypeCode . SByte ) ) ;
return StElem ( compilation . FindType ( KnownTypeCode . SByte ) ) ;
case ILOpCode . Stelem_I2 :
return StElem ( value : Pop ( ) , index : Pop ( ) , array : Pop ( ) , type : compilation . FindType ( KnownTypeCode . Int16 ) ) ;
return StElem ( compilation . FindType ( KnownTypeCode . Int16 ) ) ;
case ILOpCode . Stelem_I4 :
return StElem ( value : Pop ( ) , index : Pop ( ) , array : Pop ( ) , type : compilation . FindType ( KnownTypeCode . Int32 ) ) ;
return StElem ( compilation . FindType ( KnownTypeCode . Int32 ) ) ;
case ILOpCode . Stelem_I8 :
return StElem ( value : Pop ( ) , index : Pop ( ) , array : Pop ( ) , type : compilation . FindType ( KnownTypeCode . Int64 ) ) ;
return StElem ( compilation . FindType ( KnownTypeCode . Int64 ) ) ;
case ILOpCode . Stelem_R4 :
return StElem ( value : Pop ( ) , index : Pop ( ) , array : Pop ( ) , type : compilation . FindType ( KnownTypeCode . Single ) ) ;
return StElem ( compilation . FindType ( KnownTypeCode . Single ) ) ;
case ILOpCode . Stelem_R8 :
return StElem ( value : Pop ( ) , index : Pop ( ) , array : Pop ( ) , type : compilation . FindType ( KnownTypeCode . Double ) ) ;
return StElem ( compilation . FindType ( KnownTypeCode . Double ) ) ;
case ILOpCode . Stelem_I :
return StElem ( value : Pop ( ) , index : Pop ( ) , array : Pop ( ) , type : compilation . FindType ( KnownTypeCode . IntPtr ) ) ;
return StElem ( compilation . FindType ( KnownTypeCode . IntPtr ) ) ;
case ILOpCode . Stelem_Ref :
return StElem ( value : Pop ( ) , index : Pop ( ) , array : Pop ( ) , type : compilation . FindType ( KnownTypeCode . Object ) ) ;
return StElem ( compilation . FindType ( KnownTypeCode . Object ) ) ;
case ILOpCode . Stobj :
return new Void ( new StObj ( value : Pop ( ) , target : Pop ( ) , type : ReadAndDecodeTypeReference ( ) ) ) ;
return new StObj ( value : Pop ( ) , target : Pop ( ) , type : ReadAndDecodeTypeReference ( ) ) ;
case ILOpCode . Throw :
return new Throw ( Pop ( ) ) ;
case ILOpCode . Unbox :
return new Unbox ( Pop ( ) , ReadAndDecodeTypeReference ( ) ) ;
return Push ( new Unbox ( Pop ( ) , ReadAndDecodeTypeReference ( ) ) ) ;
case ILOpCode . Unbox_Any :
return new UnboxAny ( Pop ( ) , ReadAndDecodeTypeReference ( ) ) ;
return Push ( new UnboxAny ( Pop ( ) , ReadAndDecodeTypeReference ( ) ) ) ;
default :
throw new NotImplementedException ( ilOpCode . ToString ( ) ) ;
}
}
private IL . Pop Pop ( )
StackType PeekStackType ( )
{
if ( stack . Count > 0 ) {
return new IL . Pop ( stack . Pop ( ) ) ;
} else {
Warn ( "Stack underflow" ) ;
return new IL . Pop ( StackType . Unknown ) ;
}
if ( currentStack . IsEmpty )
return StackType . Unknown ;
else
return currentStack . Peek ( ) . StackType ;
}
class CollectStackVariablesVisitor : ILVisitor < ILInstruction >
{
readonly UnionFind < ILVariable > unionFind ;
internal readonly HashSet < ILVariable > variables = new HashSet < ILVariable > ( ) ;
public CollectStackVariablesVisitor ( UnionFind < ILVariable > unionFind )
{
Debug . Assert ( unionFind ! = null ) ;
this . unionFind = unionFind ;
}
protected override ILInstruction Default ( ILInstruction inst )
{
foreach ( var child in inst . Children ) {
var newChild = child . AcceptVisitor ( this ) ;
if ( newChild ! = child )
child . ReplaceWith ( newChild ) ;
}
return inst ;
}
protected internal override ILInstruction VisitLdLoc ( LdLoc inst )
{
base . VisitLdLoc ( inst ) ;
if ( inst . Variable . Kind = = VariableKind . StackSlot ) {
var variable = unionFind . Find ( inst . Variable ) ;
if ( variables . Add ( variable ) )
variable . Name = "S_" + ( variables . Count - 1 ) ;
return new LdLoc ( variable ) { ILRange = inst . ILRange } ;
}
return inst ;
}
protected internal override ILInstruction VisitStLoc ( StLoc inst )
{
base . VisitStLoc ( inst ) ;
if ( inst . Variable . Kind = = VariableKind . StackSlot ) {
var variable = unionFind . Find ( inst . Variable ) ;
if ( variables . Add ( variable ) )
variable . Name = "S_" + ( variables . Count - 1 ) ;
return new StLoc ( variable , inst . Value ) { ILRange = inst . ILRange } ;
}
return inst ;
}
}
ILInstruction Push ( ILInstruction inst )
{
Debug . Assert ( inst . ResultType ! = StackType . Void ) ;
var v = new ILVariable ( VariableKind . StackSlot , inst . ResultType , inst . ILRange . Start ) ;
v . Name = "S_" + inst . ILRange . Start . ToString ( "x4" ) ;
currentStack = currentStack . Push ( v ) ;
return new StLoc ( v , inst ) ;
}
IL . LdLoc Peek ( )
{
// TODO: handle stack underflow?
return new LdLoc ( currentStack . Peek ( ) ) ;
}
IL . LdLoc Pop ( )
{
// TODO: handle stack underflow?
ILVariable v ;
currentStack = currentStack . Pop ( out v ) ;
return new LdLoc ( v ) ;
}
private ILInstruction Return ( )
{
@ -733,7 +826,7 @@ namespace ICSharpCode.Decompiler.IL
@@ -733,7 +826,7 @@ namespace ICSharpCode.Decompiler.IL
private ILInstruction Starg ( ushort v )
{
return new Void ( new StLoc ( parameterVariables [ v ] , Pop ( ) ) ) ;
return new StLoc ( parameterVariables [ v ] , Pop ( ) ) ;
}
private ILInstruction Ldloc ( ushort v )
@ -748,17 +841,20 @@ namespace ICSharpCode.Decompiler.IL
@@ -748,17 +841,20 @@ namespace ICSharpCode.Decompiler.IL
private ILInstruction Stloc ( ushort v )
{
return new Void ( new StLoc ( localVariables [ v ] , Pop ( ) ) ) ;
return new StLoc ( localVariables [ v ] , Pop ( ) ) ;
}
private ILInstruction LdElem ( ILInstruction array , ILInstruction index , I Type type )
private ILInstruction LdElem ( IType type )
{
return new LdObj ( new LdElema ( array , index , type ) , type ) ;
return Push ( new LdObj ( new LdElema ( index : Pop ( ) , array : Pop ( ) , type : type ) , type ) ) ;
}
private ILInstruction StElem ( ILInstruction array , ILInstruction index , ILInstruction value , I Type type )
private ILInstruction StElem ( IType type )
{
return new Void ( new StObj ( new LdElema ( array , index , type ) , value , type ) ) ;
var value = Pop ( ) ;
var index = Pop ( ) ;
var array = Pop ( ) ;
return new StObj ( new LdElema ( array , index , type ) , value , type ) ;
}
ILInstruction InitObj ( ILInstruction target , IType type )
@ -789,7 +885,7 @@ namespace ICSharpCode.Decompiler.IL
@@ -789,7 +885,7 @@ namespace ICSharpCode.Decompiler.IL
{
byte alignment = reader . ReadByte ( ) ;
var inst = DecodeInstruction ( ) ;
var sup = UnpackVoid ( inst ) as ISupportsUnalignedPrefix ;
var sup = inst as ISupportsUnalignedPrefix ;
if ( sup ! = null )
sup . UnalignedPrefix = alignment ;
else
@ -800,7 +896,7 @@ namespace ICSharpCode.Decompiler.IL
@@ -800,7 +896,7 @@ namespace ICSharpCode.Decompiler.IL
private ILInstruction DecodeVolatile ( )
{
var inst = DecodeInstruction ( ) ;
var svp = UnpackVoid ( inst ) as ISupportsVolatilePrefix ;
var svp = inst as ISupportsVolatilePrefix ;
if ( svp ! = null )
svp . IsVolatile = true ;
else
@ -808,12 +904,6 @@ namespace ICSharpCode.Decompiler.IL
@@ -808,12 +904,6 @@ namespace ICSharpCode.Decompiler.IL
return inst ;
}
ILInstruction UnpackVoid ( ILInstruction inst )
{
Void v = inst as Void ;
return v ! = null ? v . Argument : inst ;
}
private ILInstruction DecodeReadonly ( )
{
var inst = DecodeInstruction ( ) ;
@ -834,7 +924,10 @@ namespace ICSharpCode.Decompiler.IL
@@ -834,7 +924,10 @@ namespace ICSharpCode.Decompiler.IL
}
var call = CallInstruction . Create ( opCode , method ) ;
call . Arguments . AddRange ( arguments ) ;
return call ;
if ( call . ResultType ! = StackType . Void )
return Push ( call ) ;
else
return call ;
}
static int GetPopCount ( OpCode callCode , MethodReference methodReference )
@ -858,10 +951,12 @@ namespace ICSharpCode.Decompiler.IL
@@ -858,10 +951,12 @@ namespace ICSharpCode.Decompiler.IL
var right = Pop ( ) ;
var left = Pop ( ) ;
// Based on Table 4: Binary Comparison or Branch Operation
OpCode opCode ;
if ( left . ResultType = = StackType . F & & right . ResultType = = StackType . F )
return BinaryComparisonInstruction . Create ( opCode_F , left , right ) ;
opCode = opCode_F ;
else
return BinaryComparisonInstruction . Create ( opCode_I , left , right ) ;
opCode = opCode_I ;
return BinaryComparisonInstruction . Create ( opCode , left , right ) ;
}
ILInstruction DecodeComparisonBranch ( bool shortForm , OpCode comparisonOpCodeForInts , OpCode comparisonOpCodeForFloats , bool negate )
@ -911,21 +1006,17 @@ namespace ICSharpCode.Decompiler.IL
@@ -911,21 +1006,17 @@ namespace ICSharpCode.Decompiler.IL
{
int target = shortForm ? reader . ReadSByte ( ) : reader . ReadInt32 ( ) ;
target + = reader . Position ;
int popCount = 0 ;
if ( isLeave ) {
popCount = stack . Count ;
stack . Clear ( ) ;
currentStack = currentStack . Clear ( ) ;
}
MarkBranchTarget ( target ) ;
return new Branch ( target ) { PopCount = popCount } ;
return new Branch ( target ) ;
}
void MarkBranchTarget ( int targetILOffset )
{
isBranchTarget [ targetILOffset ] = true ;
if ( targetILOffset > = reader . Position ) {
branchStackDict [ targetILOffset ] = stack . ToImmutableArray ( ) ;
}
StoreStackForOffset ( targetILOffset , currentStack ) ;
}
ILInstruction DecodeSwitch ( )
@ -950,7 +1041,7 @@ namespace ICSharpCode.Decompiler.IL
@@ -950,7 +1041,7 @@ namespace ICSharpCode.Decompiler.IL
{
var right = Pop ( ) ;
var left = Pop ( ) ;
return BinaryNumericInstruction . Create ( opCode , left , right , checkForOverflow , sign ) ;
return Push ( BinaryNumericInstruction . Create ( opCode , left , right , checkForOverflow , sign ) ) ;
}
}
}