private void ProcessCallSiteCaching(IfStatement theIf, FieldDefinition callSiteField)
        {
            MethodInvocationExpression binderMethodInvocation = GetBinderMethodInvocation(theIf.Then.Statements.Last() as ExpressionStatement, callSiteField);
            CallSiteInfo callSiteInfo = new CallSiteInfo(callSiteField, binderMethodInvocation.MethodExpression.Method.Name);

            int index = 0;

            if (callSiteInfo.BinderType == CallSiteBinderType.GetMember || callSiteInfo.BinderType == CallSiteBinderType.InvokeMember ||
                callSiteInfo.BinderType == CallSiteBinderType.SetMember || callSiteInfo.BinderType == CallSiteBinderType.IsEvent)
            {
                GetMemberNameArgument(binderMethodInvocation, callSiteInfo);
            }

            if (callSiteInfo.BinderType == CallSiteBinderType.BinaryOperation || callSiteInfo.BinderType == CallSiteBinderType.UnaryOperation)
            {
                GetOperatorArgument(binderMethodInvocation, callSiteInfo);
            }

            if (callSiteInfo.BinderType == CallSiteBinderType.Convert)
            {
                GetConvertTypeArgument(binderMethodInvocation, callSiteInfo);
            }

            if (callSiteInfo.BinderType == CallSiteBinderType.InvokeMember)
            {
                VariableReference typeArrayVariable = GetTypeArrayVariable(binderMethodInvocation);
                if (typeArrayVariable != null)
                {
                    callSiteInfo.GenericTypeArguments = new List <TypeReference>();
                    ProcessArgumentArray(theIf.Then.Statements, ref index, typeArrayVariable, callSiteInfo, GetGenericTypeArgument);
                }
            }

            if (callSiteInfo.BinderType != CallSiteBinderType.Convert && callSiteInfo.BinderType != CallSiteBinderType.IsEvent)
            {
                ProcessArgumentArray(theIf.Then.Statements, ref index, GetArgumentArrayVariable(binderMethodInvocation), callSiteInfo, GetDynamicArgument);
            }
            else
            {
                callSiteInfo.DynamicArgumentIndices.Add(0);
            }

            fieldToCallSiteInfoMap.Add(callSiteField, callSiteInfo);
        }
 private void ProcessCallSiteCaching(IfStatement theIf, FieldDefinition callSiteField)
 {
     V_0 = this.GetBinderMethodInvocation(theIf.get_Then().get_Statements().Last <Statement>() as ExpressionStatement, callSiteField);
     V_1 = new CallSiteInfo(callSiteField, V_0.get_MethodExpression().get_Method().get_Name());
     V_2 = 0;
     if (V_1.get_BinderType() == 3 || V_1.get_BinderType() == 6 || V_1.get_BinderType() == 9 || V_1.get_BinderType() == 7)
     {
         this.GetMemberNameArgument(V_0, V_1);
     }
     if (V_1.get_BinderType() == CallSiteBinderType.BinaryOperation || V_1.get_BinderType() == 10)
     {
         this.GetOperatorArgument(V_0, V_1);
     }
     if (V_1.get_BinderType() == 1)
     {
         this.GetConvertTypeArgument(V_0, V_1);
     }
     if (V_1.get_BinderType() == 6)
     {
         V_3 = this.GetTypeArrayVariable(V_0);
         if (V_3 != null)
         {
             V_1.set_GenericTypeArguments(new List <TypeReference>());
             this.ProcessArgumentArray(theIf.get_Then().get_Statements(), ref V_2, V_3, V_1, new Action <MethodInvocationExpression, int, CallSiteInfo>(this.GetGenericTypeArgument));
         }
     }
     if (V_1.get_BinderType() == 1 || V_1.get_BinderType() == 7)
     {
         V_1.get_DynamicArgumentIndices().Add(0);
     }
     else
     {
         this.ProcessArgumentArray(theIf.get_Then().get_Statements(), ref V_2, this.GetArgumentArrayVariable(V_0), V_1, new Action <MethodInvocationExpression, int, CallSiteInfo>(this.GetDynamicArgument));
     }
     this.fieldToCallSiteInfoMap.Add(callSiteField, V_1);
     return;
 }
        private void GetDynamicArgument(MethodInvocationExpression expression, int index, CallSiteInfo callSiteInfo)
        {
            if (expression.MethodExpression.Method.Name != "Create" ||
                expression.MethodExpression.Target != null ||
                expression.MethodExpression.Method.DeclaringType.GetFriendlyFullName(null) != "Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo" ||
                expression.Arguments.Count != 2 || expression.Arguments[0].CodeNodeType != CodeNodeType.LiteralExpression)
            {
                throw new Exception(InvalidStatementExceptionString);
            }

            int argumentInfoFlag = Convert.ToInt32((expression.Arguments[0] as LiteralExpression).Value);

            if ((argumentInfoFlag & UseCompileTimeType) == 0)
            {
                callSiteInfo.DynamicArgumentIndices.Add(index);
            }
        }
        private void GetGenericTypeArgument(MethodInvocationExpression expression, int index, CallSiteInfo callSiteInfo)
        {
            TypeReference typeRef;

            if (!expression.IsTypeOfExpression(out typeRef))
            {
                throw new Exception(InvalidStatementExceptionString);
            }

            callSiteInfo.GenericTypeArguments.Add(typeRef);
        }
        private void ProcessArgumentArray(StatementCollection statements, ref int index, VariableReference typesArray, CallSiteInfo callSiteInfo,
                                          Action <MethodInvocationExpression, int, CallSiteInfo> action)
        {
            if ((statements[index] is ExpressionStatement) && ((statements[index] as ExpressionStatement).Expression is BinaryExpression))
            {
                BinaryExpression binaryExpression = (statements[index] as ExpressionStatement).Expression as BinaryExpression;
                if (binaryExpression.IsAssignmentExpression && (binaryExpression.Left is VariableReferenceExpression) && (binaryExpression.Right is MethodInvocationExpression))
                {
                    index++;
                }
            }

            int arraySize = CheckNewArrayInitializationAndSize(statements[index++], typesArray);

            for (int i = 0; i < arraySize; i++)
            {
                if (!statements[index].IsAssignmentStatement())
                {
                    throw new Exception(InvalidStatementExceptionString);
                }

                BinaryExpression elementAssignment = (statements[index++] as ExpressionStatement).Expression as BinaryExpression;
                if (elementAssignment.Left.CodeNodeType != CodeNodeType.ArrayIndexerExpression ||
                    !CheckArrayIndexerExpression(elementAssignment.Left as ArrayIndexerExpression, typesArray, i) ||
                    elementAssignment.Right.CodeNodeType != CodeNodeType.MethodInvocationExpression)
                {
                    throw new Exception(InvalidStatementExceptionString);
                }

                action(elementAssignment.Right as MethodInvocationExpression, i, callSiteInfo);
            }
        }
        private void GetConvertTypeArgument(MethodInvocationExpression binderInvocation, CallSiteInfo callSiteInfo)
        {
            int           typeArgumentIndex = 1;
            TypeReference typeRef;

            if (binderInvocation.Arguments[typeArgumentIndex].CodeNodeType != CodeNodeType.MethodInvocationExpression ||
                !(binderInvocation.Arguments[typeArgumentIndex] as MethodInvocationExpression).IsTypeOfExpression(out typeRef))
            {
                throw new Exception("Invalid argument: convert type.");
            }

            callSiteInfo.ConvertType = typeRef;
        }
        private void GetOperatorArgument(MethodInvocationExpression binderInvocation, CallSiteInfo callSiteInfo)
        {
            int operatorIndex = 1;

            if (binderInvocation.Arguments[operatorIndex].CodeNodeType != CodeNodeType.LiteralExpression)
            {
                throw new Exception("Invalid argument: operator.");
            }

            callSiteInfo.Operator = (ExpressionType)Convert.ToInt32((binderInvocation.Arguments[operatorIndex] as LiteralExpression).Value);
        }
        private void GetMemberNameArgument(MethodInvocationExpression binderInvocation, CallSiteInfo callSiteInfo)
        {
            int memberNameIndex = 1;

            if (binderInvocation.Arguments[memberNameIndex].CodeNodeType == CodeNodeType.LiteralExpression)
            {
                callSiteInfo.MemberName = (binderInvocation.Arguments[memberNameIndex] as LiteralExpression).Value as string;
                if (callSiteInfo.MemberName != null)
                {
                    return;
                }
            }
            throw new Exception("Invalid argument: member name.");
        }
 private void GetDynamicArgument(MethodInvocationExpression expression, int index, CallSiteInfo callSiteInfo)
 {
     if (String.op_Inequality(expression.get_MethodExpression().get_Method().get_Name(), "Create") || expression.get_MethodExpression().get_Target() != null || String.op_Inequality(expression.get_MethodExpression().get_Method().get_DeclaringType().GetFriendlyFullName(null), "Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo") || expression.get_Arguments().get_Count() != 2 || expression.get_Arguments().get_Item(0).get_CodeNodeType() != 22)
     {
         throw new Exception("Invalid statement.");
     }
     if (Convert.ToInt32((expression.get_Arguments().get_Item(0) as LiteralExpression).get_Value()) & 1 == 0)
     {
         callSiteInfo.get_DynamicArgumentIndices().Add(index);
     }
     return;
 }
        ILInstruction MakeDynamicInstruction(CallSiteInfo callsite, CallVirt targetInvokeCall, List <ILInstruction> deadArguments)
        {
            switch (callsite.Kind)
            {
            case BinderMethodKind.BinaryOperation:
                deadArguments.AddRange(targetInvokeCall.Arguments.Take(2));
                return(new DynamicBinaryOperatorInstruction(
                           binderFlags: callsite.Flags,
                           operation: callsite.Operation,
                           context: callsite.Context,
                           leftArgumentInfo: callsite.ArgumentInfos[0],
                           left: targetInvokeCall.Arguments[2],
                           rightArgumentInfo: callsite.ArgumentInfos[1],
                           right: targetInvokeCall.Arguments[3]
                           ));

            case BinderMethodKind.Convert:
                deadArguments.AddRange(targetInvokeCall.Arguments.Take(2));
                ILInstruction result = new DynamicConvertInstruction(
                    binderFlags: callsite.Flags,
                    context: callsite.Context,
                    type: callsite.ConvertTargetType,
                    argument: targetInvokeCall.Arguments[2]
                    );
                if (result.ResultType == StackType.Unknown)
                {
                    // if references are missing, we need to coerce the primitive type to None.
                    // Otherwise we will get loads of assertions.
                    result = new Conv(result, PrimitiveType.None, ((DynamicConvertInstruction)result).IsChecked, Sign.None);
                }
                return(result);

            case BinderMethodKind.GetIndex:
                deadArguments.AddRange(targetInvokeCall.Arguments.Take(2));
                return(new DynamicGetIndexInstruction(
                           binderFlags: callsite.Flags,
                           context: callsite.Context,
                           argumentInfo: callsite.ArgumentInfos,
                           arguments: targetInvokeCall.Arguments.Skip(2).ToArray()
                           ));

            case BinderMethodKind.GetMember:
                deadArguments.AddRange(targetInvokeCall.Arguments.Take(2));
                return(new DynamicGetMemberInstruction(
                           binderFlags: callsite.Flags,
                           name: callsite.MemberName,
                           context: callsite.Context,
                           targetArgumentInfo: callsite.ArgumentInfos[0],
                           target: targetInvokeCall.Arguments[2]
                           ));

            case BinderMethodKind.Invoke:
                deadArguments.AddRange(targetInvokeCall.Arguments.Take(2));
                return(new DynamicInvokeInstruction(
                           binderFlags: callsite.Flags,
                           context: callsite.Context,
                           argumentInfo: callsite.ArgumentInfos,
                           arguments: targetInvokeCall.Arguments.Skip(2).ToArray()
                           ));

            case BinderMethodKind.InvokeConstructor:
                deadArguments.AddRange(targetInvokeCall.Arguments.Take(2));
                return(new DynamicInvokeConstructorInstruction(
                           binderFlags: callsite.Flags,
                           context: callsite.Context,
                           argumentInfo: callsite.ArgumentInfos,
                           arguments: targetInvokeCall.Arguments.Skip(2).ToArray()
                           ));

            case BinderMethodKind.InvokeMember:
                deadArguments.AddRange(targetInvokeCall.Arguments.Take(2));
                return(new DynamicInvokeMemberInstruction(
                           binderFlags: callsite.Flags,
                           name: callsite.MemberName,
                           typeArguments: callsite.TypeArguments,
                           context: callsite.Context,
                           argumentInfo: callsite.ArgumentInfos,
                           arguments: targetInvokeCall.Arguments.Skip(2).ToArray()
                           ));

            case BinderMethodKind.IsEvent:
                deadArguments.AddRange(targetInvokeCall.Arguments.Take(2));
                return(new DynamicIsEventInstruction(
                           binderFlags: callsite.Flags,
                           name: callsite.MemberName,
                           context: callsite.Context,
                           argument: targetInvokeCall.Arguments[2]
                           ));

            case BinderMethodKind.SetIndex:
                deadArguments.AddRange(targetInvokeCall.Arguments.Take(2));
                return(new DynamicSetIndexInstruction(
                           binderFlags: callsite.Flags,
                           context: callsite.Context,
                           argumentInfo: callsite.ArgumentInfos,
                           arguments: targetInvokeCall.Arguments.Skip(2).ToArray()
                           ));

            case BinderMethodKind.SetMember:
                deadArguments.AddRange(targetInvokeCall.Arguments.Take(2));
                return(new DynamicSetMemberInstruction(
                           binderFlags: callsite.Flags,
                           name: callsite.MemberName,
                           context: callsite.Context,
                           targetArgumentInfo: callsite.ArgumentInfos[0],
                           target: targetInvokeCall.Arguments[2],
                           valueArgumentInfo: callsite.ArgumentInfos[1],
                           value: targetInvokeCall.Arguments[3]
                           ));

            case BinderMethodKind.UnaryOperation:
                deadArguments.AddRange(targetInvokeCall.Arguments.Take(2));
                return(new DynamicUnaryOperatorInstruction(
                           binderFlags: callsite.Flags,
                           operation: callsite.Operation,
                           context: callsite.Context,
                           operandArgumentInfo: callsite.ArgumentInfos[0],
                           operand: targetInvokeCall.Arguments[2]
                           ));

            default:
                throw new ArgumentOutOfRangeException($"Value {callsite.Kind} is not supported!");
            }
        }
 private void ProcessArgumentArray(StatementCollection statements, ref int index, VariableReference typesArray, CallSiteInfo callSiteInfo, Action <MethodInvocationExpression, int, CallSiteInfo> action)
 {
     if (statements.get_Item(index) as ExpressionStatement != null && (statements.get_Item(index) as ExpressionStatement).get_Expression() as BinaryExpression != null)
     {
         V_1 = (statements.get_Item(index) as ExpressionStatement).get_Expression() as BinaryExpression;
         if (V_1.get_IsAssignmentExpression() && V_1.get_Left() as VariableReferenceExpression != null && V_1.get_Right() as MethodInvocationExpression != null)
         {
             index = index + 1;
         }
     }
     V_2   = index;
     index = V_2 + 1;
     V_0   = this.CheckNewArrayInitializationAndSize(statements.get_Item(V_2), typesArray);
     V_3   = 0;
     while (V_3 < V_0)
     {
         if (!statements.get_Item(index).IsAssignmentStatement())
         {
             throw new Exception("Invalid statement.");
         }
         V_2   = index;
         index = V_2 + 1;
         V_4   = (statements.get_Item(V_2) as ExpressionStatement).get_Expression() as BinaryExpression;
         if (V_4.get_Left().get_CodeNodeType() != 39 || !this.CheckArrayIndexerExpression(V_4.get_Left() as ArrayIndexerExpression, typesArray, V_3) || V_4.get_Right().get_CodeNodeType() != 19)
         {
             throw new Exception("Invalid statement.");
         }
         action.Invoke(V_4.get_Right() as MethodInvocationExpression, V_3, callSiteInfo);
         V_3 = V_3 + 1;
     }
     return;
 }
 private void GetOperatorArgument(MethodInvocationExpression binderInvocation, CallSiteInfo callSiteInfo)
 {
     V_0 = 1;
     if (binderInvocation.get_Arguments().get_Item(V_0).get_CodeNodeType() != 22)
     {
         throw new Exception("Invalid argument: operator.");
     }
     callSiteInfo.set_Operator(Convert.ToInt32((binderInvocation.get_Arguments().get_Item(V_0) as LiteralExpression).get_Value()));
     return;
 }
 private void GetMemberNameArgument(MethodInvocationExpression binderInvocation, CallSiteInfo callSiteInfo)
 {
     V_0 = 1;
     if (binderInvocation.get_Arguments().get_Item(V_0).get_CodeNodeType() == 22)
     {
         callSiteInfo.set_MemberName((binderInvocation.get_Arguments().get_Item(V_0) as LiteralExpression).get_Value() as String);
         if (callSiteInfo.get_MemberName() != null)
         {
             return;
         }
     }
     throw new Exception("Invalid argument: member name.");
 }
 private void GetGenericTypeArgument(MethodInvocationExpression expression, int index, CallSiteInfo callSiteInfo)
 {
     if (!expression.IsTypeOfExpression(out V_0))
     {
         throw new Exception("Invalid statement.");
     }
     callSiteInfo.get_GenericTypeArguments().Add(V_0);
     return;
 }
Exemplo n.º 15
0
        ILInstruction MakeDynamicInstruction(CallSiteInfo callsite, CallVirt targetInvokeCall, List <ILInstruction> deadArguments)
        {
            switch (callsite.Kind)
            {
            case BinderMethodKind.BinaryOperation:
                deadArguments.AddRange(targetInvokeCall.Arguments.Take(2));
                return(new DynamicBinaryOperatorInstruction(
                           binderFlags: callsite.Flags,
                           operation: callsite.Operation,
                           context: callsite.Context,
                           leftArgumentInfo: callsite.ArgumentInfos[0],
                           left: targetInvokeCall.Arguments[2],
                           rightArgumentInfo: callsite.ArgumentInfos[1],
                           right: targetInvokeCall.Arguments[3]
                           ));

            case BinderMethodKind.Convert:
                deadArguments.AddRange(targetInvokeCall.Arguments.Take(2));
                ILInstruction result = new DynamicConvertInstruction(
                    binderFlags: callsite.Flags,
                    context: callsite.Context,
                    type: callsite.ConvertTargetType,
                    argument: targetInvokeCall.Arguments[2]
                    );
                if (result.ResultType == StackType.Unknown)
                {
                    // if references are missing, we need to coerce the primitive type to None.
                    // Otherwise we will get loads of assertions.
                    result = new Conv(result, PrimitiveType.None, ((DynamicConvertInstruction)result).IsChecked, Sign.None);
                }
                return(result);

            case BinderMethodKind.GetIndex:
                deadArguments.AddRange(targetInvokeCall.Arguments.Take(2));
                return(new DynamicGetIndexInstruction(
                           binderFlags: callsite.Flags,
                           context: callsite.Context,
                           argumentInfo: callsite.ArgumentInfos,
                           arguments: targetInvokeCall.Arguments.Skip(2).ToArray()
                           ));

            case BinderMethodKind.GetMember:
                deadArguments.AddRange(targetInvokeCall.Arguments.Take(2));
                return(new DynamicGetMemberInstruction(
                           binderFlags: callsite.Flags,
                           name: callsite.MemberName,
                           context: callsite.Context,
                           targetArgumentInfo: callsite.ArgumentInfos[0],
                           target: targetInvokeCall.Arguments[2]
                           ));

            case BinderMethodKind.Invoke:
                deadArguments.AddRange(targetInvokeCall.Arguments.Take(2));
                return(new DynamicInvokeInstruction(
                           binderFlags: callsite.Flags,
                           context: callsite.Context,
                           argumentInfo: callsite.ArgumentInfos,
                           arguments: targetInvokeCall.Arguments.Skip(2).ToArray()
                           ));

            case BinderMethodKind.InvokeConstructor:
                var arguments = targetInvokeCall.Arguments.Skip(2).ToArray();
                // Extract type information from targetInvokeCall:
                // Must either be an inlined type or
                // a reference to a variable that is initialized with a type.
                if (!TransformExpressionTrees.MatchGetTypeFromHandle(arguments[0], out var type))
                {
                    if (!(arguments[0].MatchLdLoc(out var temp) && temp.IsSingleDefinition && temp.StoreInstructions.FirstOrDefault() is StLoc initStore))
                    {
                        return(null);
                    }
                    if (!TransformExpressionTrees.MatchGetTypeFromHandle(initStore.Value, out type))
                    {
                        return(null);
                    }
                }
                deadArguments.AddRange(targetInvokeCall.Arguments.Take(2));
                return(new DynamicInvokeConstructorInstruction(
                           binderFlags: callsite.Flags,
                           type: type ?? SpecialType.UnknownType,
                           context: callsite.Context,
                           argumentInfo: callsite.ArgumentInfos,
                           arguments: arguments
                           ));

            case BinderMethodKind.InvokeMember:
                deadArguments.AddRange(targetInvokeCall.Arguments.Take(2));
                return(new DynamicInvokeMemberInstruction(
                           binderFlags: callsite.Flags,
                           name: callsite.MemberName,
                           typeArguments: callsite.TypeArguments,
                           context: callsite.Context,
                           argumentInfo: callsite.ArgumentInfos,
                           arguments: targetInvokeCall.Arguments.Skip(2).ToArray()
                           ));

            case BinderMethodKind.IsEvent:
                deadArguments.AddRange(targetInvokeCall.Arguments.Take(2));
                return(new DynamicIsEventInstruction(
                           binderFlags: callsite.Flags,
                           name: callsite.MemberName,
                           context: callsite.Context,
                           argument: targetInvokeCall.Arguments[2]
                           ));

            case BinderMethodKind.SetIndex:
                deadArguments.AddRange(targetInvokeCall.Arguments.Take(2));
                return(new DynamicSetIndexInstruction(
                           binderFlags: callsite.Flags,
                           context: callsite.Context,
                           argumentInfo: callsite.ArgumentInfos,
                           arguments: targetInvokeCall.Arguments.Skip(2).ToArray()
                           ));

            case BinderMethodKind.SetMember:
                deadArguments.AddRange(targetInvokeCall.Arguments.Take(2));
                return(new DynamicSetMemberInstruction(
                           binderFlags: callsite.Flags,
                           name: callsite.MemberName,
                           context: callsite.Context,
                           targetArgumentInfo: callsite.ArgumentInfos[0],
                           target: targetInvokeCall.Arguments[2],
                           valueArgumentInfo: callsite.ArgumentInfos[1],
                           value: targetInvokeCall.Arguments[3]
                           ));

            case BinderMethodKind.UnaryOperation:
                deadArguments.AddRange(targetInvokeCall.Arguments.Take(2));
                return(new DynamicUnaryOperatorInstruction(
                           binderFlags: callsite.Flags,
                           operation: callsite.Operation,
                           context: callsite.Context,
                           operandArgumentInfo: callsite.ArgumentInfos[0],
                           operand: targetInvokeCall.Arguments[2]
                           ));

            default:
                throw new ArgumentOutOfRangeException($"Value {callsite.Kind} is not supported!");
            }
        }
Exemplo n.º 16
0
        bool ScanCallSiteInitBlock(Block callSiteInitBlock, IField callSiteCacheField, IType callSiteDelegateType, out CallSiteInfo callSiteInfo, out Block blockAfterInit)
        {
            callSiteInfo   = default(CallSiteInfo);
            blockAfterInit = null;
            int instCount = callSiteInitBlock.Instructions.Count;

            if (callSiteInitBlock.IncomingEdgeCount != 1 || instCount < 2)
            {
                return(false);
            }
            if (!callSiteInitBlock.Instructions[instCount - 1].MatchBranch(out blockAfterInit))
            {
                return(false);
            }
            if (!callSiteInitBlock.Instructions[instCount - 2].MatchStsFld(out var field, out var value) || !field.Equals(callSiteCacheField))
            {
                return(false);
            }
            if (!(value is Call createBinderCall) || createBinderCall.Method.TypeArguments.Count != 0 || createBinderCall.Arguments.Count != 1 || createBinderCall.Method.Name != "Create" || createBinderCall.Method.DeclaringType.FullName != CallSiteTypeName || createBinderCall.Method.DeclaringType.TypeArguments.Count != 1)
            {
                return(false);
            }
            if (!(createBinderCall.Arguments[0] is Call binderCall) || binderCall.Method.DeclaringType.FullName != CSharpBinderTypeName || binderCall.Method.DeclaringType.TypeParameterCount != 0)
            {
                return(false);
            }
            callSiteInfo.DelegateType = callSiteDelegateType;
            callSiteInfo.InitBlock    = callSiteInitBlock;
            switch (binderCall.Method.Name)
            {
            case "IsEvent":
                callSiteInfo.Kind = BinderMethodKind.IsEvent;
                // In the case of Binder.IsEvent all arguments should already be properly inlined, as there is no array initializer:
                // Scan arguments: binder flags, member name, context type
                if (binderCall.Arguments.Count != 3)
                {
                    return(false);
                }
                if (!binderCall.Arguments[0].MatchLdcI4(out int binderFlagsInteger))
                {
                    return(false);
                }
                callSiteInfo.Flags = (CSharpBinderFlags)binderFlagsInteger;
                if (!binderCall.Arguments[1].MatchLdStr(out string name))
                {
                    return(false);
                }
                callSiteInfo.MemberName = name;
                if (!TransformExpressionTrees.MatchGetTypeFromHandle(binderCall.Arguments[2], out var contextType))
                {
                    return(false);
                }
                callSiteInfo.Context = contextType;
                return(true);

            case "Convert":
                callSiteInfo.Kind = BinderMethodKind.Convert;
                // In the case of Binder.Convert all arguments should already be properly inlined, as there is no array initializer:
                // Scan arguments: binder flags, target type, context type
                if (binderCall.Arguments.Count != 3)
                {
                    return(false);
                }
                if (!binderCall.Arguments[0].MatchLdcI4(out binderFlagsInteger))
                {
                    return(false);
                }
                callSiteInfo.Flags = (CSharpBinderFlags)binderFlagsInteger;
                if (!TransformExpressionTrees.MatchGetTypeFromHandle(binderCall.Arguments[1], out var targetType))
                {
                    return(false);
                }
                callSiteInfo.ConvertTargetType = targetType;
                if (!TransformExpressionTrees.MatchGetTypeFromHandle(binderCall.Arguments[2], out contextType))
                {
                    return(false);
                }
                callSiteInfo.Context = contextType;
                return(true);

            case "InvokeMember":
                callSiteInfo.Kind = BinderMethodKind.InvokeMember;
                if (binderCall.Arguments.Count != 5)
                {
                    return(false);
                }
                // First argument: binder flags
                // The value must be a single ldc.i4 instruction.
                if (!binderCall.Arguments[0].MatchLdLoc(out var variable))
                {
                    return(false);
                }
                if (!callSiteInitBlock.Instructions[0].MatchStLoc(variable, out value))
                {
                    return(false);
                }
                if (!value.MatchLdcI4(out binderFlagsInteger))
                {
                    return(false);
                }
                callSiteInfo.Flags = (CSharpBinderFlags)binderFlagsInteger;
                // Second argument: method name
                // The value must be a single ldstr instruction.
                if (!binderCall.Arguments[1].MatchLdLoc(out variable))
                {
                    return(false);
                }
                if (!callSiteInitBlock.Instructions[1].MatchStLoc(variable, out value))
                {
                    return(false);
                }
                if (!value.MatchLdStr(out name))
                {
                    return(false);
                }
                callSiteInfo.MemberName = name;
                // Third argument: type arguments
                // The value must be either ldnull (no type arguments) or an array initializer pattern.
                if (!binderCall.Arguments[2].MatchLdLoc(out variable))
                {
                    return(false);
                }
                if (!callSiteInitBlock.Instructions[2].MatchStLoc(out var variableOrTemporary, out value))
                {
                    return(false);
                }
                int numberOfTypeArguments = 0;
                if (!value.MatchLdNull())
                {
                    if (value is NewArr typeArgsNewArr && typeArgsNewArr.Type.IsKnownType(KnownTypeCode.Type) && typeArgsNewArr.Indices.Count == 1 && typeArgsNewArr.Indices[0].MatchLdcI4(out numberOfTypeArguments))
                    {
                        if (!TransformArrayInitializers.HandleSimpleArrayInitializer(context.Function, callSiteInitBlock, 3, variableOrTemporary, typeArgsNewArr.Type, new[] { numberOfTypeArguments }, out var typeArguments, out _))
                        {
                            return(false);
                        }
                        int i = 0;
                        callSiteInfo.TypeArguments = new IType[numberOfTypeArguments];
                        foreach (var(_, typeArg) in typeArguments)
                        {
                            if (!TransformExpressionTrees.MatchGetTypeFromHandle(typeArg, out var type))
                            {
                                return(false);
                            }
                            callSiteInfo.TypeArguments[i] = type;
                            i++;
                        }
                    }
                    else
                    {
                        return(false);
                    }
                }
                int typeArgumentsOffset = numberOfTypeArguments;
                // Special case for csc array initializers:
                if (variableOrTemporary != variable)
                {
                    // store temporary from array initializer in variable
                    if (!callSiteInitBlock.Instructions[3 + typeArgumentsOffset].MatchStLoc(variable, out value))
                    {
                        return(false);
                    }
                    if (!value.MatchLdLoc(variableOrTemporary))
                    {
                        return(false);
                    }
                    typeArgumentsOffset++;
                }
                // Fourth argument: context type
                if (!binderCall.Arguments[3].MatchLdLoc(out variable))
                {
                    return(false);
                }
                if (!callSiteInitBlock.Instructions[3 + typeArgumentsOffset].MatchStLoc(variable, out value))
                {
                    return(false);
                }
                if (!TransformExpressionTrees.MatchGetTypeFromHandle(value, out contextType))
                {
                    return(false);
                }
                callSiteInfo.Context = contextType;
                // Fifth argument: call parameter info
                if (!binderCall.Arguments[4].MatchLdLoc(out variable))
                {
                    return(false);
                }
                if (!callSiteInitBlock.Instructions[4 + typeArgumentsOffset].MatchStLoc(variable, out value))
                {
                    return(false);
                }
                if (!ExtractArgumentInfo(value, ref callSiteInfo, 5 + typeArgumentsOffset, variable))
                {
                    return(false);
                }
                return(true);
 private void GetConvertTypeArgument(MethodInvocationExpression binderInvocation, CallSiteInfo callSiteInfo)
 {
     V_0 = 1;
     if (binderInvocation.get_Arguments().get_Item(V_0).get_CodeNodeType() != 19 || !(binderInvocation.get_Arguments().get_Item(V_0) as MethodInvocationExpression).IsTypeOfExpression(out V_1))
     {
         throw new Exception("Invalid argument: convert type.");
     }
     callSiteInfo.set_ConvertType(V_1);
     return;
 }