예제 #1
0
        public MethodReference ConsumeArgMethodRef(Instruction methodRefInstruction)
        {
            return(ConsumeArgMethodRefBuilder(methodRefInstruction).Build());

            MethodRefBuilder ConsumeArgMethodRefBuilder(Instruction instruction)
            {
                if (instruction.OpCode.FlowControl != FlowControl.Call || !(instruction.Operand is MethodReference method))
                {
                    throw UnexpectedInstruction(instruction, "a method call");
                }

                switch (method.FullName)
                {
                case "System.Void InlineIL.MethodRef::.ctor(InlineIL.TypeRef,System.String,InlineIL.TypeRef[])":
                {
                    var args       = _il.GetArgumentPushInstructionsInSameBasicBlock(instruction);
                    var typeRef    = ConsumeArgTypeRef(args[0]);
                    var methodName = ConsumeArgString(args[1]);
                    var paramTypes = ConsumeArgArray(args[2], ConsumeArgTypeRefBuilder);
                    var builder    = MethodRefBuilder.MethodByNameAndSignature(Module, typeRef, methodName, null, paramTypes);

                    _il.Remove(instruction);
                    return(builder);
                }

                case "System.Void InlineIL.MethodRef::.ctor(InlineIL.TypeRef,System.String,System.Int32,InlineIL.TypeRef[])":
                {
                    var args                  = _il.GetArgumentPushInstructionsInSameBasicBlock(instruction);
                    var typeRef               = ConsumeArgTypeRef(args[0]);
                    var methodName            = ConsumeArgString(args[1]);
                    var genericParameterCount = ConsumeArgInt32(args[2]);
                    var paramTypes            = ConsumeArgArray(args[3], ConsumeArgTypeRefBuilder);
                    var builder               = MethodRefBuilder.MethodByNameAndSignature(Module, typeRef, methodName, genericParameterCount, paramTypes);

                    _il.Remove(instruction);
                    return(builder);
                }

                case "System.Void InlineIL.MethodRef::.ctor(InlineIL.TypeRef,System.String)":
                    return(FromNamedMember((typeRef, methodName) => MethodRefBuilder.MethodByName(Module, typeRef, methodName)));

                case "InlineIL.MethodRef InlineIL.MethodRef::PropertyGet(InlineIL.TypeRef,System.String)":
                    return(FromNamedMember((typeRef, propertyName) => MethodRefBuilder.PropertyGet(Module, typeRef, propertyName)));

                case "InlineIL.MethodRef InlineIL.MethodRef::PropertySet(InlineIL.TypeRef,System.String)":
                    return(FromNamedMember((typeRef, propertyName) => MethodRefBuilder.PropertySet(Module, typeRef, propertyName)));

                case "InlineIL.MethodRef InlineIL.MethodRef::EventAdd(InlineIL.TypeRef,System.String)":
                    return(FromNamedMember((typeRef, eventName) => MethodRefBuilder.EventAdd(Module, typeRef, eventName)));

                case "InlineIL.MethodRef InlineIL.MethodRef::EventRemove(InlineIL.TypeRef,System.String)":
                    return(FromNamedMember((typeRef, eventName) => MethodRefBuilder.EventRemove(Module, typeRef, eventName)));

                case "InlineIL.MethodRef InlineIL.MethodRef::EventRaise(InlineIL.TypeRef,System.String)":
                    return(FromNamedMember((typeRef, eventName) => MethodRefBuilder.EventRaise(Module, typeRef, eventName)));

                case "InlineIL.MethodRef InlineIL.MethodRef::Constructor(InlineIL.TypeRef,InlineIL.TypeRef[])":
                {
                    var args       = _il.GetArgumentPushInstructionsInSameBasicBlock(instruction);
                    var typeRef    = ConsumeArgTypeRef(args[0]);
                    var paramTypes = ConsumeArgArray(args[1], ConsumeArgTypeRefBuilder);
                    var builder    = MethodRefBuilder.Constructor(Module, typeRef, paramTypes);

                    _il.Remove(instruction);
                    return(builder);
                }

                case "InlineIL.MethodRef InlineIL.MethodRef::TypeInitializer(InlineIL.TypeRef)":
                {
                    var args    = _il.GetArgumentPushInstructionsInSameBasicBlock(instruction);
                    var typeRef = ConsumeArgTypeRef(args[0]);
                    var builder = MethodRefBuilder.TypeInitializer(Module, typeRef);

                    _il.Remove(instruction);
                    return(builder);
                }

                case "InlineIL.MethodRef InlineIL.MethodRef::MakeGenericMethod(InlineIL.TypeRef[])":
                {
                    var args        = _il.GetArgumentPushInstructionsInSameBasicBlock(instruction);
                    var builder     = ConsumeArgMethodRefBuilder(args[0]);
                    var genericArgs = ConsumeArgArray(args[1], ConsumeArgTypeRef);
                    builder.MakeGenericMethod(genericArgs);

                    _il.Remove(instruction);
                    return(builder);
                }

                case "InlineIL.MethodRef InlineIL.MethodRef::WithOptionalParameters(InlineIL.TypeRef[])":
                {
                    var args               = _il.GetArgumentPushInstructionsInSameBasicBlock(instruction);
                    var builder            = ConsumeArgMethodRefBuilder(args[0]);
                    var optionalParamTypes = ConsumeArgArray(args[1], ConsumeArgTypeRef);
                    builder.SetOptionalParameters(optionalParamTypes);

                    _il.Remove(instruction);
                    return(builder);
                }

                default:
                    throw UnexpectedInstruction(instruction, "a method reference");
                }

                MethodRefBuilder FromNamedMember(Func <TypeReference, string, MethodRefBuilder> resolver)
                {
                    var args       = _il.GetArgumentPushInstructionsInSameBasicBlock(instruction);
                    var typeRef    = ConsumeArgTypeRef(args[0]);
                    var memberName = ConsumeArgString(args[1]);
                    var builder    = resolver(typeRef, memberName);

                    _il.Remove(instruction);
                    return(builder);
                }
            }
        }
예제 #2
0
        public MethodReference ConsumeArgMethodRef(Instruction methodRefInstruction)
        {
            return(ConsumeArgMethodRefBuilder(methodRefInstruction).Build());

            MethodRefBuilder ConsumeArgMethodRefBuilder(Instruction instruction)
            {
                if (instruction.OpCode.FlowControl != FlowControl.Call || !(instruction.Operand is MethodReference method))
                {
                    throw UnexpectedInstruction(instruction, "a method call");
                }

                switch (method.GetElementMethod().FullName)
                {
                case "System.Void InlineIL.MethodRef::.ctor(InlineIL.TypeRef,System.String,InlineIL.TypeRef[])":
                case "InlineIL.MethodRef InlineIL.MethodRef::Method(InlineIL.TypeRef,System.String,InlineIL.TypeRef[])":
                {
                    var args       = _il.GetArgumentPushInstructionsInSameBasicBlock(instruction);
                    var typeRef    = ConsumeArgTypeRef(args[0]);
                    var methodName = ConsumeArgString(args[1]);
                    var paramTypes = ConsumeArgArray(args[2], ConsumeArgTypeRefBuilder);
                    var builder    = MethodRefBuilder.MethodByNameAndSignature(Module, typeRef, methodName, null, null, paramTypes);

                    _il.Remove(instruction);
                    return(builder);
                }

                case "System.Void InlineIL.MethodRef::.ctor(InlineIL.TypeRef,System.String,System.Int32,InlineIL.TypeRef[])":
                case "InlineIL.MethodRef InlineIL.MethodRef::Method(InlineIL.TypeRef,System.String,System.Int32,InlineIL.TypeRef[])":
                {
                    var args                  = _il.GetArgumentPushInstructionsInSameBasicBlock(instruction);
                    var typeRef               = ConsumeArgTypeRef(args[0]);
                    var methodName            = ConsumeArgString(args[1]);
                    var genericParameterCount = ConsumeArgInt32(args[2]);
                    var paramTypes            = ConsumeArgArray(args[3], ConsumeArgTypeRefBuilder);
                    var builder               = MethodRefBuilder.MethodByNameAndSignature(Module, typeRef, methodName, genericParameterCount, null, paramTypes);

                    _il.Remove(instruction);
                    return(builder);
                }

                case "System.Void InlineIL.MethodRef::.ctor(InlineIL.TypeRef,System.String,InlineIL.TypeRef,System.Int32,InlineIL.TypeRef[])":
                case "InlineIL.MethodRef InlineIL.MethodRef::Method(InlineIL.TypeRef,System.String,InlineIL.TypeRef,System.Int32,InlineIL.TypeRef[])":
                {
                    var args                  = _il.GetArgumentPushInstructionsInSameBasicBlock(instruction);
                    var typeRef               = ConsumeArgTypeRef(args[0]);
                    var methodName            = ConsumeArgString(args[1]);
                    var returnType            = ConsumeArgTypeRefBuilder(args[2]);
                    var genericParameterCount = ConsumeArgInt32(args[3]);
                    var paramTypes            = ConsumeArgArray(args[4], ConsumeArgTypeRefBuilder);
                    var builder               = MethodRefBuilder.MethodByNameAndSignature(Module, typeRef, methodName, genericParameterCount, returnType, paramTypes);

                    _il.Remove(instruction);
                    return(builder);
                }

                case "System.Void InlineIL.MethodRef::.ctor(InlineIL.TypeRef,System.String)":
                case "InlineIL.MethodRef InlineIL.MethodRef::Method(InlineIL.TypeRef,System.String)":
                    return(FromNamedMember((typeRef, methodName) => MethodRefBuilder.MethodByName(Module, typeRef, methodName)));

                case "InlineIL.MethodRef InlineIL.MethodRef::PropertyGet(InlineIL.TypeRef,System.String)":
                    return(FromNamedMember((typeRef, propertyName) => MethodRefBuilder.PropertyGet(Module, typeRef, propertyName)));

                case "InlineIL.MethodRef InlineIL.MethodRef::PropertySet(InlineIL.TypeRef,System.String)":
                    return(FromNamedMember((typeRef, propertyName) => MethodRefBuilder.PropertySet(Module, typeRef, propertyName)));

                case "InlineIL.MethodRef InlineIL.MethodRef::EventAdd(InlineIL.TypeRef,System.String)":
                    return(FromNamedMember((typeRef, eventName) => MethodRefBuilder.EventAdd(Module, typeRef, eventName)));

                case "InlineIL.MethodRef InlineIL.MethodRef::EventRemove(InlineIL.TypeRef,System.String)":
                    return(FromNamedMember((typeRef, eventName) => MethodRefBuilder.EventRemove(Module, typeRef, eventName)));

                case "InlineIL.MethodRef InlineIL.MethodRef::EventRaise(InlineIL.TypeRef,System.String)":
                    return(FromNamedMember((typeRef, eventName) => MethodRefBuilder.EventRaise(Module, typeRef, eventName)));

                case "InlineIL.MethodRef InlineIL.MethodRef::Constructor(InlineIL.TypeRef,InlineIL.TypeRef[])":
                {
                    var args       = _il.GetArgumentPushInstructionsInSameBasicBlock(instruction);
                    var typeRef    = ConsumeArgTypeRef(args[0]);
                    var paramTypes = ConsumeArgArray(args[1], ConsumeArgTypeRefBuilder);
                    var builder    = MethodRefBuilder.Constructor(Module, typeRef, paramTypes);

                    _il.Remove(instruction);
                    return(builder);
                }

                case "InlineIL.MethodRef InlineIL.MethodRef::TypeInitializer(InlineIL.TypeRef)":
                {
                    var args    = _il.GetArgumentPushInstructionsInSameBasicBlock(instruction);
                    var typeRef = ConsumeArgTypeRef(args[0]);
                    var builder = MethodRefBuilder.TypeInitializer(Module, typeRef);

                    _il.Remove(instruction);
                    return(builder);
                }

                case "InlineIL.MethodRef InlineIL.MethodRef::Operator(InlineIL.TypeRef,InlineIL.UnaryOperator)":
                {
                    var args    = _il.GetArgumentPushInstructionsInSameBasicBlock(instruction);
                    var typeRef = ConsumeArgTypeRef(args[0]);
                    var op      = ConsumeArgEnumInt32 <UnaryOperator>(args[1]);
                    var builder = MethodRefBuilder.Operator(Module, typeRef, op);

                    _il.Remove(instruction);
                    return(builder);
                }

                case "InlineIL.MethodRef InlineIL.MethodRef::Operator(InlineIL.TypeRef,InlineIL.BinaryOperator,InlineIL.TypeRef,InlineIL.TypeRef)":
                {
                    var args             = _il.GetArgumentPushInstructionsInSameBasicBlock(instruction);
                    var typeRef          = ConsumeArgTypeRef(args[0]);
                    var op               = ConsumeArgEnumInt32 <BinaryOperator>(args[1]);
                    var leftOperandType  = ConsumeArgTypeRefBuilder(args[2]);
                    var rightOperandType = ConsumeArgTypeRefBuilder(args[3]);
                    var builder          = MethodRefBuilder.Operator(Module, typeRef, op, leftOperandType, rightOperandType);

                    _il.Remove(instruction);
                    return(builder);
                }

                case "InlineIL.MethodRef InlineIL.MethodRef::Operator(InlineIL.TypeRef,InlineIL.ConversionOperator,InlineIL.ConversionDirection,InlineIL.TypeRef)":
                {
                    var args      = _il.GetArgumentPushInstructionsInSameBasicBlock(instruction);
                    var typeRef   = ConsumeArgTypeRef(args[0]);
                    var op        = ConsumeArgEnumInt32 <ConversionOperator>(args[1]);
                    var direction = ConsumeArgEnumInt32 <ConversionDirection>(args[2]);
                    var otherType = ConsumeArgTypeRefBuilder(args[3]);
                    var builder   = MethodRefBuilder.Operator(Module, typeRef, op, direction, otherType);

                    _il.Remove(instruction);
                    return(builder);
                }

                case "InlineIL.MethodRef InlineIL.MethodRef::FromDelegate(!!0)":
                {
                    var args    = instruction.GetArgumentPushInstructions();
                    var builder = ConsumeArgDelegate(args[0]);
                    _il.EnsureSameBasicBlock(args[0], instruction);

                    _il.Remove(instruction);
                    return(builder);
                }

                case "InlineIL.MethodRef InlineIL.MethodRef::MakeGenericMethod(InlineIL.TypeRef[])":
                {
                    var args        = _il.GetArgumentPushInstructionsInSameBasicBlock(instruction);
                    var builder     = ConsumeArgMethodRefBuilder(args[0]);
                    var genericArgs = ConsumeArgArray(args[1], ConsumeArgTypeRef);
                    builder.MakeGenericMethod(genericArgs);

                    _il.Remove(instruction);
                    return(builder);
                }

                case "InlineIL.MethodRef InlineIL.MethodRef::WithOptionalParameters(InlineIL.TypeRef[])":
                {
                    var args               = _il.GetArgumentPushInstructionsInSameBasicBlock(instruction);
                    var builder            = ConsumeArgMethodRefBuilder(args[0]);
                    var optionalParamTypes = ConsumeArgArray(args[1], ConsumeArgTypeRef);
                    builder.SetOptionalParameters(optionalParamTypes);

                    _il.Remove(instruction);
                    return(builder);
                }

                default:
                    throw UnexpectedInstruction(instruction, "a method reference");
                }

                MethodRefBuilder FromNamedMember(Func <TypeReference, string, MethodRefBuilder> resolver)
                {
                    var args       = _il.GetArgumentPushInstructionsInSameBasicBlock(instruction);
                    var typeRef    = ConsumeArgTypeRef(args[0]);
                    var memberName = ConsumeArgString(args[1]);
                    var builder    = resolver(typeRef, memberName);

                    _il.Remove(instruction);
                    return(builder);
                }
            }

            MethodRefBuilder ConsumeArgDelegate(Instruction instruction)
            {
                if (instruction.OpCode != OpCodes.Newobj)
                {
                    throw UnexpectedInstruction(instruction, "a delegate instantiation");
                }

                var args      = _il.GetArgumentPushInstructionsInSameBasicBlock(instruction);
                var methodRef = ConsumeArgLdFtn(args[1]);
                var builder   = MethodRefBuilder.MethodFromDelegateReference(Module, methodRef);

                ConsumeArgObjRefNoSideEffects(args[0]);

                _il.Remove(instruction);
                return(builder);
            }

            void ConsumeArgObjRefNoSideEffects(Instruction instruction)
            {
                switch (instruction.OpCode.Code)
                {
                // Pop 0, Push 1
                case Code.Ldnull:
                case Code.Ldarg:
                case Code.Ldarga:
                case Code.Ldloc:
                case Code.Ldloca:
                case Code.Ldsfld:
                case Code.Ldsflda:
                case Code.Sizeof:
                case Code.Dup:     // Not really pop 0, push 1, but used as an arg to ldvirtftn
                {
                    _il.Remove(instruction);
                    return;
                }

                // Pop 1, Push 1
                case Code.Box:
                case Code.Ldobj:
                case Code.Ldfld:
                case Code.Ldflda:
                {
                    var arg = _il.GetPrevSkipNopsInSameBasicBlock(instruction);
                    ConsumeArgObjRefNoSideEffects(arg);

                    _il.Remove(instruction);
                    return;
                }

                default:
                {
                    if (TryConsumeArgConst(instruction, out _))
                    {
                        return;
                    }

                    throw UnexpectedInstruction(instruction, "a side-effect free object load, or null");
                }
                }
            }

            MethodReference ConsumeArgLdFtn(Instruction instruction)
            {
                switch (instruction.OpCode.Code)
                {
                case Code.Ldftn:
                {
                    _il.Remove(instruction);
                    return((MethodReference)instruction.Operand);
                }

                case Code.Ldvirtftn:
                {
                    var arg = _il.GetPrevSkipNopsInSameBasicBlock(instruction);
                    ConsumeArgObjRefNoSideEffects(arg);

                    _il.Remove(instruction);
                    return((MethodReference)instruction.Operand);
                }

                default:
                    throw UnexpectedInstruction(instruction, "a ldftn or ldvirtftn");
                }
            }
        }