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); } } }
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"); } } }