예제 #1
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!");
            }
        }
        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!");
            }
        }