Instruction ReplaceStore(ILProcessor ilProcessor, Instruction instruction, MethodReference calledMethod) { var generic_method = calledMethod as GenericInstanceMethod; var typetok = generic_method.GenericArguments[0]; var stack = Analysis[instruction.Previous]; var operandEntry = stack.Head; var addr_instruction = operandEntry.Item1; var next = instruction.Next; if (addr_instruction.OpCode == OpCodes.Ldloca) { var local = (VariableDefinition)addr_instruction.Operand; ilProcessor.InsertBefore(addr_instruction, Instruction.Create(OpCodes.Stloc, local)); } else if (addr_instruction.OpCode == OpCodes.Ldarga) { var argument = (ParameterDefinition)addr_instruction.Operand; ilProcessor.InsertBefore(addr_instruction, Instruction.Create(OpCodes.Starg, argument)); } else if (addr_instruction.OpCode == OpCodes.Ldsflda) { var field = (FieldReference)addr_instruction.Operand; ilProcessor.InsertBefore(addr_instruction, Instruction.Create(OpCodes.Stsfld, field)); } else if (addr_instruction.OpCode == OpCodes.Ldflda) { var field = (FieldReference)addr_instruction.Operand; var value_temp = new VariableDefinition(field.FieldType); VariableDefinition addr_temp; if (field.DeclaringType.IsValueType) { addr_temp = new VariableDefinition(field.DeclaringType.MakeByReferenceType()); } else { addr_temp = new VariableDefinition(field.DeclaringType); } ilProcessor.Body.Variables.Add(value_temp); ilProcessor.Body.Variables.Add(addr_temp); ilProcessor.InsertBefore(addr_instruction, Instruction.Create(OpCodes.Stloc, addr_temp)); ilProcessor.InsertBefore(addr_instruction, Instruction.Create(OpCodes.Stloc, value_temp)); ilProcessor.InsertBefore(addr_instruction, Instruction.Create(OpCodes.Ldloc, addr_temp)); ilProcessor.InsertBefore(addr_instruction, Instruction.Create(OpCodes.Ldloc, value_temp)); ilProcessor.InsertBefore(addr_instruction, Instruction.Create(OpCodes.Stfld, field)); } else { throw new Exception("ReplaceStore: How did we get here?!"); } StackAnalyser.RemoveInstruction(ilProcessor, addr_instruction); StackAnalyser.RemoveInstruction(ilProcessor, instruction); return(next); }
protected override Instruction Visit(ILProcessor ilProcessor, Instruction instruction) { var calledMethod = instruction.Operand as MethodReference; var next = instruction.Next; if (calledMethod.Name == "KeepAlive") { StackAnalyser.RemoveInstructionChain(ilProcessor.Body.Method, instruction, Analysis); } else if (calledMethod.Name == "Load" || calledMethod.Name == "Peek") { /* * The compiler will have inserted the appropriate load * instructions to put the value on the operand stack in * preperation to call Load<T>. Thus all we have to do is * remove the call instruction, that keeps the value on the * stack instead of popping it for the call. */ StackAnalyser.RemoveInstruction(ilProcessor, instruction); } else if (calledMethod.Name == "LoadAddress") { /* * The compiler will have inserted the a load instruction, we * need to change it to the appropriate load address instruction. */ return(ReplaceLoadAddress(ilProcessor, instruction, calledMethod)); } else if (calledMethod.Name == "Store") { /* * The compiler will have inserted instructions to load the * addr of the location we want to store to. We need to look * at these instructions and replace them with the appropriate * standard store instruction. We then remove the call to Store. */ return(ReplaceStore(ilProcessor, instruction, calledMethod)); } else if (calledMethod.Name == "LoadByName") { return(ReplaceLoadByName(ilProcessor, instruction, calledMethod)); } else if (calledMethod.Name == "StoreByName") { return(ReplaceStoreByName(ilProcessor, instruction, calledMethod)); } else if (calledMethod.Name == "LoadAddressByName") { return(ReplaceLoadAddressByName(ilProcessor, instruction, calledMethod)); } else if (calledMethod.Name == "DeclareLocal") { return(ReplaceDeclareLocal(ilProcessor, instruction, calledMethod)); } else { return(ReplaceInstruction(ilProcessor, instruction, calledMethod)); } return(next); }
private Instruction ReplaceLoadAddress(ILProcessor ilProcessor, Instruction instruction, MethodReference calledMethod) { var generic_method = calledMethod as GenericInstanceMethod; var typetok = generic_method.GenericArguments[0]; var stack = Analysis[instruction.Previous]; var operandEntry = stack.Head; var addr_instruction = operandEntry.Item1; var next = instruction.Next; if (addr_instruction.OpCode == OpCodes.Ldloc) { var local = (VariableDefinition)addr_instruction.Operand; StackAnalyser.ReplaceInstruction(ilProcessor, addr_instruction, Instruction.Create(OpCodes.Ldloca, local)); } else if (addr_instruction.OpCode == OpCodes.Ldarg) { var argument = (ParameterDefinition)addr_instruction.Operand; StackAnalyser.ReplaceInstruction(ilProcessor, addr_instruction, Instruction.Create(OpCodes.Ldarga, argument)); } else if (addr_instruction.OpCode == OpCodes.Ldsfld) { var field = (FieldReference)addr_instruction.Operand; StackAnalyser.ReplaceInstruction(ilProcessor, addr_instruction, Instruction.Create(OpCodes.Ldsflda, field)); } else if (addr_instruction.OpCode == OpCodes.Ldfld) { var field = (FieldReference)addr_instruction.Operand; StackAnalyser.ReplaceInstruction(ilProcessor, addr_instruction, Instruction.Create(OpCodes.Ldflda, field)); } else if ( addr_instruction.OpCode == OpCodes.Ldelem_Any) { var type = (TypeReference)addr_instruction.Operand; StackAnalyser.ReplaceInstruction(ilProcessor, addr_instruction, Instruction.Create(OpCodes.Ldelema, type)); } else if ( addr_instruction.OpCode == OpCodes.Ldelem_I || addr_instruction.OpCode == OpCodes.Ldelem_I1 || addr_instruction.OpCode == OpCodes.Ldelem_I2 || addr_instruction.OpCode == OpCodes.Ldelem_I4 || addr_instruction.OpCode == OpCodes.Ldelem_I8 || addr_instruction.OpCode == OpCodes.Ldelem_U1 || addr_instruction.OpCode == OpCodes.Ldelem_U2 || addr_instruction.OpCode == OpCodes.Ldelem_U4 || addr_instruction.OpCode == OpCodes.Ldelem_R4 || addr_instruction.OpCode == OpCodes.Ldelem_R8 || addr_instruction.OpCode == OpCodes.Ldelem_Ref) { var module = ilProcessor.Body.Method.Module; TypeReference type; switch (addr_instruction.OpCode.Code) { case Code.Ldelem_I: type = new TypeReference("System", "IntPtr", module, module); break; case Code.Ldelem_I1: type = new TypeReference("System", "SByte", module, module); break; case Code.Ldelem_I2: type = new TypeReference("System", "Int16", module, module); break; case Code.Ldelem_I4: type = new TypeReference("System", "Int32", module, module); break; case Code.Ldelem_I8: type = new TypeReference("System", "Int64", module, module); break; case Code.Ldelem_U1: type = new TypeReference("System", "Byte", module, module); break; case Code.Ldelem_U2: type = new TypeReference("System", "UInt16", module, module); break; case Code.Ldelem_U4: type = new TypeReference("System", "UInt32", module, module); break; case Code.Ldelem_R4: type = new TypeReference("System", "Single", module, module); break; case Code.Ldelem_R8: type = new TypeReference("System", "Double", module, module); break; case Code.Ldelem_Ref: default: { // array is the lower item in the stack var array_instruction = Analysis[addr_instruction.Previous].Tail.Head.Item1; // whatever load loaded this array it will have a type with it type = array_instruction.Operand as TypeReference; } break; } StackAnalyser.ReplaceInstruction(ilProcessor, addr_instruction, Instruction.Create(OpCodes.Ldelema, type)); } else { throw new Exception("ReplaceLoadAddress: How did we get here?!"); } StackAnalyser.RemoveInstruction(ilProcessor, instruction); return(next); }