@ -18,6 +18,7 @@
using System ;
using System ;
using System.Collections.Generic ;
using System.Collections.Generic ;
using System.Diagnostics ;
using System.Linq ;
using System.Linq ;
using ICSharpCode.Decompiler.CSharp.Resolver ;
using ICSharpCode.Decompiler.CSharp.Resolver ;
using ICSharpCode.Decompiler.TypeSystem ;
using ICSharpCode.Decompiler.TypeSystem ;
@ -150,7 +151,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms
var functionType = instruction . Method . ReturnType . TypeArguments [ 0 ] ;
var functionType = instruction . Method . ReturnType . TypeArguments [ 0 ] ;
var function = new ILFunction ( functionType . TypeArguments . LastOrDefault ( ) ? ? context . TypeSystem . Compilation . FindType ( KnownTypeCode . Void ) , parameterList , container ) ;
var function = new ILFunction ( functionType . TypeArguments . LastOrDefault ( ) ? ? context . TypeSystem . Compilation . FindType ( KnownTypeCode . Void ) , parameterList , container ) ;
if ( isQuotedLambda | | lambdaStack . Count = = 0 )
if ( isQuotedLambda | | lambdaStack . Count = = 0 )
function . ExpressionTreeType = instruction . Method . ReturnType ;
function . DelegateType = instruction . Method . ReturnType ;
else
function . DelegateType = functionType ;
function . Variables . AddRange ( parameterVariablesList ) ;
function . Variables . AddRange ( parameterVariablesList ) ;
lambdaStack . Push ( function ) ;
lambdaStack . Push ( function ) ;
var ( bodyInstruction , type ) = ConvertInstruction ( instruction . Arguments [ 0 ] ) ;
var ( bodyInstruction , type ) = ConvertInstruction ( instruction . Arguments [ 0 ] ) ;
@ -159,11 +162,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return ( null , SpecialType . UnknownType ) ;
return ( null , SpecialType . UnknownType ) ;
container . ExpectedResultType = bodyInstruction . ResultType ;
container . ExpectedResultType = bodyInstruction . ResultType ;
container . Blocks . Add ( new Block ( ) { Instructions = { new Leave ( container , bodyInstruction ) } } ) ;
container . Blocks . Add ( new Block ( ) { Instructions = { new Leave ( container , bodyInstruction ) } } ) ;
if ( ! isQuotedLambda & & lambdaStack . Count > 0 )
return ( function , function . DelegateType ) ;
return ( new NewObj ( functionType . GetConstructors ( ) . Single ( ) ) {
Arguments = { new LdNull ( ) , function }
} , functionType ) ;
return ( function , function . ExpressionTreeType ) ;
}
}
bool ReadParameters ( ILInstruction initializer , IList < IParameter > parameters , IList < ILVariable > parameterVariables , ITypeResolveContext resolveContext )
bool ReadParameters ( ILInstruction initializer , IList < IParameter > parameters , IList < ILVariable > parameterVariables , ITypeResolveContext resolveContext )
@ -199,6 +198,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms
( ILInstruction , IType ) ConvertInstruction ( ILInstruction instruction )
( ILInstruction , IType ) ConvertInstruction ( ILInstruction instruction )
{
{
var result = Convert ( ) ;
if ( result . Item1 ! = null ) {
Debug . Assert ( result . Item2 ! = null , "IType must be non-null!" ) ;
Debug . Assert ( result . Item1 . ResultType = = result . Item2 . GetStackType ( ) , "StackTypes must match!" ) ;
}
return result ;
( ILInstruction , IType ) Convert ( ) {
switch ( instruction ) {
switch ( instruction ) {
case CallInstruction invocation :
case CallInstruction invocation :
if ( invocation . Method . DeclaringType . FullName ! = "System.Linq.Expressions.Expression" )
if ( invocation . Method . DeclaringType . FullName ! = "System.Linq.Expressions.Expression" )
@ -301,9 +308,30 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return ConvertTypeIs ( invocation ) ;
return ConvertTypeIs ( invocation ) ;
}
}
return ( null , SpecialType . UnknownType ) ;
return ( null , SpecialType . UnknownType ) ;
case ILFunction function :
if ( function . IsExpressionTree ) {
function . DelegateType = UnwrapExpressionTree ( function . DelegateType ) ;
}
return ( function , function . DelegateType ) ;
case LdLoc ldloc :
if ( IsExpressionTreeParameter ( ldloc . Variable ) ) {
if ( ! parameterMapping . TryGetValue ( ldloc . Variable , out var v ) )
return ( null , SpecialType . UnknownType ) ;
return ( new LdLoc ( v ) , v . Type ) ;
}
return ( null , SpecialType . UnknownType ) ;
default :
default :
return ConvertValue ( instruction , instruction . Parent ) ;
return ( null , SpecialType . UnknownType ) ;
}
}
}
IType UnwrapExpressionTree ( IType delegateType )
{
if ( delegateType is ParameterizedType pt & & pt . FullName = = "System.Linq.Expressions.Expression" & & pt . TypeArguments . Count = = 1 ) {
return pt . TypeArguments [ 0 ] ;
}
}
return delegateType ;
}
}
( ILInstruction , IType ) ConvertArrayIndex ( CallInstruction invocation )
( ILInstruction , IType ) ConvertArrayIndex ( CallInstruction invocation )
@ -534,11 +562,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return ( null , SpecialType . UnknownType ) ;
return ( null , SpecialType . UnknownType ) ;
if ( value . MatchBox ( out var arg , out var boxType ) ) {
if ( value . MatchBox ( out var arg , out var boxType ) ) {
if ( boxType . Kind = = TypeKind . Enum | | boxType . IsKnownType ( KnownTypeCode . Boolean ) )
if ( boxType . Kind = = TypeKind . Enum | | boxType . IsKnownType ( KnownTypeCode . Boolean ) )
return ( new ExpressionTreeCast ( boxType , ConvertValue ( arg , invocation ) . Item1 , false ) , boxType ) ;
return ( new ExpressionTreeCast ( boxType , ConvertValue ( arg , invocation ) , false ) , boxType ) ;
value = ConvertValue ( arg , invocation ) . Item1 ;
value = ConvertValue ( arg , invocation ) ;
return ( value , type ) ;
return ( value , type ) ;
}
}
return ConvertValue ( value , invocation ) ;
return ( ConvertValue ( value , invocation ) , type ) ;
}
}
( ILInstruction , IType ) ConvertElementInit ( CallInstruction invocation )
( ILInstruction , IType ) ConvertElementInit ( CallInstruction invocation )
@ -727,7 +755,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return ( null , SpecialType . UnknownType ) ;
return ( null , SpecialType . UnknownType ) ;
indices [ i ] = index ;
indices [ i ] = index ;
}
}
return ( new NewArr ( type , indices ) , type ) ;
return ( new NewArr ( type , indices ) , new ArrayType ( context . TypeSystem . Compilation , type , arguments . Count ) ) ;
}
}
( ILInstruction , IType ) ConvertNewArrayInit ( CallInstruction invocation )
( ILInstruction , IType ) ConvertNewArrayInit ( CallInstruction invocation )
@ -764,10 +792,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms
switch ( invocation . Arguments . Count ) {
switch ( invocation . Arguments . Count ) {
case 1 :
case 1 :
if ( MatchGetTypeFromHandle ( invocation . Arguments [ 0 ] , out var type ) ) {
if ( MatchGetTypeFromHandle ( invocation . Arguments [ 0 ] , out var type ) ) {
var ctors = type . GetConstructors ( ) . ToArray ( ) ;
var ctor = type . GetConstructors ( c = > c . Parameters . Count = = 0 ) . FirstOrDefault ( ) ;
if ( ctors . Length ! = 1 | | ctors [ 0 ] . Parameters . Count > 0 )
if ( ctor = = null )
return ( null , SpecialType . UnknownType ) ;
return ( null , SpecialType . UnknownType ) ;
return ( new NewObj ( ctors [ 0 ] ) , type ) ;
return ( new NewObj ( ctor ) , type ) ;
}
}
if ( MatchGetConstructorFromHandle ( invocation . Arguments [ 0 ] , out member ) ) {
if ( MatchGetConstructorFromHandle ( invocation . Arguments [ 0 ] , out member ) ) {
return ( new NewObj ( ( IMethod ) member ) , member . DeclaringType ) ;
return ( new NewObj ( ( IMethod ) member ) , member . DeclaringType ) ;
@ -917,27 +945,25 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return ( null , SpecialType . UnknownType ) ;
return ( null , SpecialType . UnknownType ) ;
}
}
( ILInstruction , IType ) ConvertValue ( ILInstruction value , ILInstruction context )
ILInstruction ConvertValue ( ILInstruction value , ILInstruction context )
{
{
switch ( value ) {
switch ( value ) {
case LdLoc ldloc :
case LdLoc ldloc :
if ( IsExpressionTreeParameter ( ldloc . Variable ) ) {
if ( IsExpressionTreeParameter ( ldloc . Variable ) ) {
if ( ! parameterMapping . TryGetValue ( ldloc . Variable , out var v ) )
if ( ! parameterMapping . TryGetValue ( ldloc . Variable , out var v ) )
return ( null , SpecialType . UnknownType ) ;
return null ;
if ( context is CallInstruction parentCall
if ( context is CallInstruction parentCall
& & parentCall . Method . FullName = = "System.Linq.Expressions.Expression.Call"
& & parentCall . Method . FullName = = "System.Linq.Expressions.Expression.Call"
& & v . StackType . IsIntegerType ( ) )
& & v . StackType . IsIntegerType ( ) )
return ( new LdLoca ( v ) , new ByReferenceType ( v . Type ) ) ;
return new LdLoca ( v ) ;
return ( new LdLoc ( v ) , v . Type ) ;
return null ;
} else {
} else {
if ( ldloc . Variable . Kind ! = VariableKind . StackSlot )
if ( ldloc . Variable . Kind ! = VariableKind . StackSlot )
return ( new LdLoc ( ldloc . Variable ) , ldloc . Variable . Typ e ) ;
return new LdLoc ( ldloc . Variable ) ;
return ( null , SpecialType . UnknownType ) ;
return null ;
}
}
default :
default :
if ( SemanticHelper . IsPure ( value . Flags ) )
return value . Clone ( ) ;
return ( value . Clone ( ) , value . InferType ( ) ) ;
return ( value , value . InferType ( ) ) ;
}
}
}
}