public MethodBody(MethodDefinition meth) { m_method = meth; m_instructions = new InstructionCollection (this); m_exceptions = new ExceptionHandlerCollection (this); m_variables = new VariableDefinitionCollection (this); }
void MarkBlockStarts (InstructionCollection instructions) { Instruction instruction = instructions[0]; // the first instruction starts a block MarkBlockStart (instruction); for (int i = 1; i < instructions.Count; ++i) { instruction = instructions[i]; if (!IsBlockDelimiter (instruction)) continue; if (HasMultipleBranches (instruction)) { // each switch case first instruction starts a block foreach (Instruction target in GetBranchTargets (instruction)) if (target != null) MarkBlockStart (target); } else { // the target of a branch starts a block Instruction target = GetBranchTarget (instruction); if (null != target) MarkBlockStart (target); } // the next instruction after a branch starts a block if (null != instruction.Next) MarkBlockStart (instruction.Next); } }
public override void VisitInstructionCollection(InstructionCollection instructions) { foreach (Instruction instruction in instructions) { instruction.Accept(this); } }
private void Init([NonNull] InstructionCollection instructions, [NonNull] MethodDefinition method) { this.instructions = instructions; this.method = method; BuildGraph(); }
public override void VisitInstructionCollection (InstructionCollection instructionCollection) { foreach (Instruction instruction in instructionCollection) { if (IsDelimiter (instruction)) CreateExpressionAndAddToExpressionContainer (); if (IsAcceptable (instruction)) AddToExpression (instruction); } }
public override void VisitInstructionCollection(InstructionCollection instructions) { MethodBody body = instructions.Container; long start = m_codeWriter.BaseStream.Position; ComputeMaxStack(instructions); foreach (Instruction instr in instructions) { instr.Offset = (int)(m_codeWriter.BaseStream.Position - start); if (instr.OpCode.Size == 1) { m_codeWriter.Write(instr.OpCode.Op2); } else { m_codeWriter.Write(instr.OpCode.Op1); m_codeWriter.Write(instr.OpCode.Op2); } if (instr.OpCode.OperandType != OperandType.InlineNone && instr.Operand == null) { throw new ReflectionException("OpCode {0} have null operand", instr.OpCode.Name); } switch (instr.OpCode.OperandType) { case OperandType.InlineNone: break; case OperandType.InlineSwitch: Instruction[] targets = (Instruction[])instr.Operand; for (int i = 0; i < targets.Length + 1; i++) { m_codeWriter.Write((uint)0); } break; case OperandType.ShortInlineBrTarget: m_codeWriter.Write((byte)0); break; case OperandType.InlineBrTarget: m_codeWriter.Write(0); break; case OperandType.ShortInlineI: if (instr.OpCode == OpCodes.Ldc_I4_S) { m_codeWriter.Write((sbyte)instr.Operand); } else { m_codeWriter.Write((byte)instr.Operand); } break; case OperandType.ShortInlineVar: m_codeWriter.Write((byte)body.Variables.IndexOf( (VariableDefinition)instr.Operand)); break; case OperandType.ShortInlineParam: m_codeWriter.Write((byte)GetParameterIndex(body, (ParameterDefinition)instr.Operand)); break; case OperandType.InlineSig: WriteToken(GetCallSiteToken((CallSite)instr.Operand)); break; case OperandType.InlineI: m_codeWriter.Write((int)instr.Operand); break; case OperandType.InlineVar: m_codeWriter.Write((short)body.Variables.IndexOf( (VariableDefinition)instr.Operand)); break; case OperandType.InlineParam: m_codeWriter.Write((short)GetParameterIndex( body, (ParameterDefinition)instr.Operand)); break; case OperandType.InlineI8: m_codeWriter.Write((long)instr.Operand); break; case OperandType.ShortInlineR: m_codeWriter.Write((float)instr.Operand); break; case OperandType.InlineR: m_codeWriter.Write((double)instr.Operand); break; case OperandType.InlineString: WriteToken(new MetadataToken(TokenType.String, m_reflectWriter.MetadataWriter.AddUserString(instr.Operand as string))); break; case OperandType.InlineField: if (instr.Operand is FieldReference) { WriteToken((instr.Operand as FieldReference).MetadataToken); } else { throw new ReflectionException("Wrong operand for InlineField: {0}", instr.Operand.GetType().FullName); } break; case OperandType.InlineMethod: if (instr.Operand is GenericInstanceMethod) { WriteToken(m_reflectWriter.GetMethodSpecToken(instr.Operand as GenericInstanceMethod)); } else if (instr.Operand is MethodReference) { WriteToken((instr.Operand as MethodReference).MetadataToken); } else { throw new ReflectionException("Wrong operand for InlineMethod: {0}", instr.Operand.GetType().FullName); } break; case OperandType.InlineType: if (instr.Operand is TypeReference) { WriteToken(m_reflectWriter.GetTypeDefOrRefToken( instr.Operand as TypeReference)); } else { throw new ReflectionException("Wrong operand for InlineType: {0}", instr.Operand.GetType().FullName); } break; case OperandType.InlineTok: if (instr.Operand is TypeReference) { WriteToken(m_reflectWriter.GetTypeDefOrRefToken( instr.Operand as TypeReference)); } else if (instr.Operand is GenericInstanceMethod) { WriteToken(m_reflectWriter.GetMethodSpecToken(instr.Operand as GenericInstanceMethod)); } else if (instr.Operand is IMetadataTokenProvider) { WriteToken((instr.Operand as IMetadataTokenProvider).MetadataToken); } else { throw new ReflectionException( string.Format("Wrong operand for {0} OpCode: {1}", instr.OpCode.OperandType, instr.Operand.GetType().FullName)); } break; } } long pos = m_codeWriter.BaseStream.Position; foreach (Instruction instr in instructions) { switch (instr.OpCode.OperandType) { case OperandType.InlineSwitch: m_codeWriter.BaseStream.Position = instr.Offset + instr.OpCode.Size; Instruction[] targets = (Instruction[])instr.Operand; m_codeWriter.Write((uint)targets.Length); foreach (Instruction tgt in targets) { m_codeWriter.Write((tgt.Offset - (instr.Offset + instr.OpCode.Size + (4 * (targets.Length + 1))))); } break; case OperandType.ShortInlineBrTarget: m_codeWriter.BaseStream.Position = instr.Offset + instr.OpCode.Size; m_codeWriter.Write((byte)(((Instruction)instr.Operand).Offset - (instr.Offset + instr.OpCode.Size + 1))); break; case OperandType.InlineBrTarget: m_codeWriter.BaseStream.Position = instr.Offset + instr.OpCode.Size; m_codeWriter.Write(((Instruction)instr.Operand).Offset - (instr.Offset + instr.OpCode.Size + 4)); break; } } m_codeWriter.BaseStream.Position = pos; }
void ComputeMaxStack (InstructionCollection instructions) { InstructionCollection ehs = new InstructionCollection (null); foreach (ExceptionHandler eh in instructions.Container.ExceptionHandlers) switch (eh.Type) { case ExceptionHandlerType.Catch : ehs.Add (eh.HandlerStart); break; case ExceptionHandlerType.Filter : ehs.Add (eh.FilterStart); break; } int max = 0, current = 0; foreach (Instruction instr in instructions) { if (ehs.Contains (instr)) current++; switch (instr.OpCode.StackBehaviourPush) { case StackBehaviour.Push1: case StackBehaviour.Pushi: case StackBehaviour.Pushi8: case StackBehaviour.Pushr4: case StackBehaviour.Pushr8: case StackBehaviour.Pushref: case StackBehaviour.Varpush: current++; break; case StackBehaviour.Push1_push1: current += 2; break; } if (max < current) max = current; switch (instr.OpCode.StackBehaviourPop) { case StackBehaviour.Varpop: break; case StackBehaviour.Pop1: case StackBehaviour.Popi: case StackBehaviour.Popref: current--; break; case StackBehaviour.Pop1_pop1: case StackBehaviour.Popi_pop1: case StackBehaviour.Popi_popi: case StackBehaviour.Popi_popi8: case StackBehaviour.Popi_popr4: case StackBehaviour.Popi_popr8: case StackBehaviour.Popref_pop1: case StackBehaviour.Popref_popi: current -= 2; break; case StackBehaviour.Popi_popi_popi: case StackBehaviour.Popref_popi_popi: case StackBehaviour.Popref_popi_popi8: case StackBehaviour.Popref_popi_popr4: case StackBehaviour.Popref_popi_popr8: case StackBehaviour.Popref_popi_popref: current -= 3; break; } } instructions.Container.MaxStack = max; }
public void VisitInstructionCollection (InstructionCollection instructions) { foreach (Instruction instr in instructions) instr.Accept (this); }
void MarkBlockEnds (InstructionCollection instructions) { InstructionBlock [] blocks = this.RegisteredBlocks; InstructionBlock current = blocks [0]; for (int i = 1; i < blocks.Length; ++i) { InstructionBlock block = blocks [i]; current.SetLastInstruction (block.FirstInstruction.Previous); current = block; } current.SetLastInstruction (instructions [instructions.Count - 1]); }
static bool IsRangeFat(Instruction start, Instruction end, InstructionCollection instructions) { return(GetLength(start, end, instructions) >= 256 || start.Offset >= 65536); }
void MarkBlockEnds (InstructionCollection instructions) { var blocks = ToArray (); var current = blocks [0]; for (int i = 1; i < blocks.Length; ++i) { var block = blocks [i]; current.Last = block.First.Previous; current = block; } current.Last = instructions [instructions.Count - 1]; }
/// <summary> /// Reads method calls by extracting instrunctions /// </summary> /// <param name="method"></param> /// <param name="methodDefinition"></param> /// <param name="instructions"></param> public void ReadInstructions(Method method, MethodDefinition methodDefinition, InstructionCollection instructions) { foreach (Instruction instruction in instructions) { var instr = ReadInstruction(instruction); if (instr is MethodDefinition) { var md = instr as MethodDefinition; var type = (from n in method.Type.Namespace.Module.Namespaces from t in n.Types where t.Name == FormatTypeName(md.DeclaringType) && n.Name == t.Namespace.Name select t).SingleOrDefault(); method.TypeUses.Add(type); var findTargetMethod = (from m in type.Methods where m.Name == FormatMethodName(md) select m).SingleOrDefault(); if (findTargetMethod != null && type == method.Type) method.MethodUses.Add(findTargetMethod); } if (instr is FieldDefinition) { var fd = instr as FieldDefinition; var field = (from f in method.Type.Fields where f.Name == fd.Name select f).SingleOrDefault(); if (field != null) method.FieldUses.Add(field); } } }
public override void VisitInstructionCollection(InstructionCollection instructions) { for (var i = 0; i < instructions.Count; i++) this.VisitInstruction(instructions[i]); }
internal CilWorker(MethodBody body) { m_mbody = body; m_instrs = m_mbody.Instructions; }
public BasicBlock([NonNull] InstructionCollection instructions) { this.instructions = instructions; }
static void ComputeMaxStack(InstructionCollection instructions) { InstructionCollection ehs = new InstructionCollection(null); foreach (ExceptionHandler eh in instructions.Container.ExceptionHandlers) { switch (eh.Type) { case ExceptionHandlerType.Catch: ehs.Add(eh.HandlerStart); break; case ExceptionHandlerType.Filter: ehs.Add(eh.FilterStart); break; } } int max = 0, current = 0; foreach (Instruction instr in instructions) { if (ehs.Contains(instr)) { current++; } switch (instr.OpCode.StackBehaviourPush) { case StackBehaviour.Push1: case StackBehaviour.Pushi: case StackBehaviour.Pushi8: case StackBehaviour.Pushr4: case StackBehaviour.Pushr8: case StackBehaviour.Pushref: case StackBehaviour.Varpush: current++; break; case StackBehaviour.Push1_push1: current += 2; break; } if (max < current) { max = current; } switch (instr.OpCode.StackBehaviourPop) { case StackBehaviour.Varpop: break; case StackBehaviour.Pop1: case StackBehaviour.Popi: case StackBehaviour.Popref: current--; break; case StackBehaviour.Pop1_pop1: case StackBehaviour.Popi_pop1: case StackBehaviour.Popi_popi: case StackBehaviour.Popi_popi8: case StackBehaviour.Popi_popr4: case StackBehaviour.Popi_popr8: case StackBehaviour.Popref_pop1: case StackBehaviour.Popref_popi: current -= 2; break; case StackBehaviour.Popi_popi_popi: case StackBehaviour.Popref_popi_popi: case StackBehaviour.Popref_popi_popi8: case StackBehaviour.Popref_popi_popr4: case StackBehaviour.Popref_popi_popr8: case StackBehaviour.Popref_popi_popref: current -= 3; break; } if (current < 0) { current = 0; } } instructions.Container.MaxStack = max; }
public MethodBody(MethodDefinition meth) { m_method = meth; // there is always a RET instruction (if a body is present) m_instructions = new InstructionCollection(this); }
private static FieldReference DoGetOwnedField(TypeDefinition type, InstructionCollection instructions, int index) { FieldReference owned = null; Instruction instruction = instructions[index]; if (instruction.OpCode.Code == Code.Stfld) { FieldReference fr = (FieldReference) instruction.Operand; FieldDefinition field = type.Fields.GetField(fr.Name); if (field != null && field.MetadataToken == fr.MetadataToken) { if (!field.IsStatic) // we should be checking the store field's target to see if it is 'this', but hopefully ctors won't be assigning to other class instances { do { // newobj instance void class [mscorlib]System.IO.StringWriter::.ctor() // stfld class [mscorlib]System.IO.StringWriter Smokey.DisposableFieldsTest/GoodCase::m_writer if (instructions[index - 1].OpCode.Code == Code.Newobj || instructions[index - 1].OpCode.Code == Code.Newarr) { owned = field; break; } // call native int class Smokey.DisposeNativeResourcesTest/GoodCase2::CreateHandle() // stfld native int Smokey.DisposeNativeResourcesTest/GoodCase2::m_resource if (instructions[index - 1].OpCode.Code == Code.Call || instructions[index - 1].OpCode.Code == Code.Callvirt) { MethodReference target = (MethodReference) instructions[index - 1].Operand; if (!target.Name.StartsWith("get_") && target.Name != "op_Explicit") // ignore property and (IntPtr) 0 { if (target.ToString().IndexOf("Create") >= 0 || target.ToString().IndexOf("Make") >= 0) { owned = field; break; } } } } while (false); } } } // ldarg.0 this // ldflda System.Runtime.InteropServices.HandleRef Smokey.Tests.DisposeNativeResourcesTest/BadCase2::m_resource // ldc.i4.s 0x64 // call instance void native int::'.ctor'(int32) // // ldarg.0 // ldflda valuetype [mscorlib]System.Runtime.InteropServices.HandleRef Smokey.Tests.DisposeNativeResourcesTest/BadCase3::m_resource // initobj [mscorlib]System.Runtime.InteropServices.HandleRef else if (instruction.OpCode.Code == Code.Ldflda) { if (instructions[index - 1].OpCode.Code == Code.Ldarg_0) { FieldReference fr = (FieldReference) instruction.Operand; FieldDefinition field = type.Fields.GetField(fr.Name); if (field != null && field.MetadataToken == fr.MetadataToken) { if (!field.IsStatic) { int i = index + 1; while (i < instructions.Count) { if (DoIsLoad(instructions[i].OpCode.Code)) ++i; else break; } if (i < instructions.Count) { if (instructions[i].OpCode.Code == Code.Call || instructions[i].OpCode.Code == Code.Callvirt) { MethodReference target = (MethodReference) instructions[i].Operand; if (target.ToString().IndexOf("ctor") >= 0 || target.ToString().IndexOf("Create") >= 0 || target.ToString().IndexOf("Make") >= 0) { owned = field; } } else if (instructions[i].OpCode.Code == Code.Initobj) { owned = field; } } } } } } return owned; }
internal ILProcessor(MethodBody body) { this.body = body; this.instructions = (InstructionCollection)body.Instructions; }
public MethodBody (MethodDefinition meth) { m_method = meth; // there is always a RET instruction (if a body is present) m_instructions = new InstructionCollection (this); }
public override void VisitInstructionCollection (InstructionCollection instructions) { foreach (Instruction instr in instructions) { CheckExceptionHandlers (instr); m_writer.Write ("{0}: {1}", Label (instr), instr.OpCode.Name); switch (instr.OpCode.OperandType) { case OperandType.InlineNone : break; case OperandType.InlineSwitch : m_writer.WriteLine ("("); m_writer.Indent (); Instruction [] targets = (Instruction []) instr.Operand; for (int i = 0; i < targets.Length; i++) { m_writer.Write (Label (targets [i])); m_writer.WriteLine (i < targets.Length - 1 ? "," : string.Empty); } m_writer.Unindent (); m_writer.Write (")"); break; case OperandType.ShortInlineBrTarget : case OperandType.InlineBrTarget : m_writer.WriteLine (Label ((Instruction) instr.Operand)); break; case OperandType.ShortInlineVar : case OperandType.InlineVar : VariableDefinition var = (VariableDefinition) instr.Operand; if (var.Name != null && var.Name.Length > 0) m_writer.Write (var.Name); else m_writer.Write (instructions.Container.Variables.IndexOf (var)); break; case OperandType.ShortInlineParam : case OperandType.InlineParam : ParameterDefinition param = (ParameterDefinition) instr.Operand; if (param.Name != null && param.Name.Length > 0) m_writer.Write (Formater.Escape (param.Name)); else m_writer.Write (instructions.Container.Method.Parameters.IndexOf (param)); break; case OperandType.InlineI : case OperandType.InlineI8 : case OperandType.InlineR : case OperandType.ShortInlineI : case OperandType.ShortInlineR : m_writer.Write (instr.Operand.ToString ()); break; case OperandType.InlineString : // FIXME: Handle unicode strings with non zero high byte //StringBuilder sb = new StringBuilder (instr.Operand.ToString ()); // FIXME: extract to a method //sb.Replace ("\"", "\\\""); //sb.Replace ("\t", "\\t"); //sb.Replace ("\r", "\\r"); //sb.Replace ("\n", "\\n"); String s = Formater.LiteralReplace(instr.Operand.ToString()); m_writer.Write(String.Concat("\"", s, "\"")); break; case OperandType.InlineType : m_writer.Write (Formater.Signature ((TypeReference) instr.Operand)); break; case OperandType.InlineMethod : case OperandType.InlineField : VisitMemberReference (instr.Operand as MemberReference); break; case OperandType.InlineTok : if (instr.Operand is TypeReference) { m_writer.Write (Formater.Signature ((TypeReference) instr.Operand, true)); } else if (instr.Operand is MemberReference) { if (instr.Operand is FieldReference) m_writer.Write ("field"); //FIXME: method VisitMemberReference ((MemberReference) instr.Operand); } break; } m_writer.WriteLine (); } }
public override void VisitInstructionCollection(InstructionCollection instructions) { for (int i = 0; i < instructions.Count; i++) { if (_jumpDestination != null) { for (int j = 0; j < instructions.Count; j++) { if (instructions[j].Offset == _jumpDestination.Offset) { i = j; _jumpDestination = null; break; } } throw new InvalidOperationException("Did not jump when expected to jump."); } VisitInstruction(instructions[i]); } }
static int GetLength(Instruction start, Instruction end, InstructionCollection instructions) { Instruction last = instructions[instructions.Count - 1]; return((end == instructions.Outside ? last.Offset + GetSize(last) : end.Offset) - start.Offset); }
internal CilWorker (MethodBody body) { m_mbody = body; m_instrs = m_mbody.Instructions; }
void ComputeMaxStack (InstructionCollection instructions) { int current = 0; int max = 0; m_stackSizes.Clear (); foreach (ExceptionHandler eh in instructions.Container.ExceptionHandlers) { switch (eh.Type) { case ExceptionHandlerType.Catch : case ExceptionHandlerType.Filter : m_stackSizes [eh.HandlerStart] = 1; max = 1; break; } } foreach (Instruction instr in instructions) { object savedSize = m_stackSizes [instr]; if (savedSize != null) current = (int) savedSize; current -= GetPopDelta (instructions.Container.Method, instr, current); if (current < 0) current = 0; current += GetPushDelta (instr); if (current > max) max = current; // for forward branches, copy the stack size for the instruction that is being branched to switch (instr.OpCode.OperandType) { case OperandType.InlineBrTarget: case OperandType.ShortInlineBrTarget: m_stackSizes [instr.Operand] = current; break; case OperandType.InlineSwitch: foreach (Instruction target in (Instruction []) instr.Operand) m_stackSizes [target] = current; break; } switch (instr.OpCode.FlowControl) { case FlowControl.Branch: case FlowControl.Throw: case FlowControl.Return: // next statement is not reachable from this statement, so reset the stack depth to 0 current = 0; break; } } instructions.Container.MaxStack = max + 1; // you never know }
void ReadCilBody(MethodBody body, BinaryReader br, out IDictionary instructions) { long start = br.BaseStream.Position; Instruction last = null; InstructionCollection code = body.Instructions; instructions = new Hashtable(); GenericContext context = new GenericContext(body.Method); while (br.BaseStream.Position < start + body.CodeSize) { OpCode op; long offset = br.BaseStream.Position - start; int cursor = br.ReadByte(); if (cursor == 0xfe) { op = OpCodes.TwoBytesOpCode [br.ReadByte()]; } else { op = OpCodes.OneByteOpCode [cursor]; } Instruction instr = new Instruction((int)offset, op); switch (op.OperandType) { case OperandType.InlineNone: break; case OperandType.InlineSwitch: uint length = br.ReadUInt32(); int [] branches = new int [length]; int [] buf = new int [length]; for (int i = 0; i < length; i++) { buf [i] = br.ReadInt32(); } for (int i = 0; i < length; i++) { branches [i] = Convert.ToInt32(br.BaseStream.Position - start + buf [i]); } instr.Operand = branches; break; case OperandType.ShortInlineBrTarget: sbyte sbrtgt = br.ReadSByte(); instr.Operand = Convert.ToInt32(br.BaseStream.Position - start + sbrtgt); break; case OperandType.InlineBrTarget: int brtgt = br.ReadInt32(); instr.Operand = Convert.ToInt32(br.BaseStream.Position - start + brtgt); break; case OperandType.ShortInlineI: if (op == OpCodes.Ldc_I4_S) { instr.Operand = br.ReadSByte(); } else { instr.Operand = br.ReadByte(); } break; case OperandType.ShortInlineVar: instr.Operand = GetVariable(body, br.ReadByte()); break; case OperandType.ShortInlineParam: instr.Operand = GetParameter(body, br.ReadByte()); break; case OperandType.InlineSig: instr.Operand = GetCallSiteAt(br.ReadInt32(), context); break; case OperandType.InlineI: instr.Operand = br.ReadInt32(); break; case OperandType.InlineVar: instr.Operand = GetVariable(body, br.ReadInt16()); break; case OperandType.InlineParam: instr.Operand = GetParameter(body, br.ReadInt16()); break; case OperandType.InlineI8: instr.Operand = br.ReadInt64(); break; case OperandType.ShortInlineR: instr.Operand = br.ReadSingle(); break; case OperandType.InlineR: instr.Operand = br.ReadDouble(); break; case OperandType.InlineString: instr.Operand = m_root.Streams.UserStringsHeap [GetRid(br.ReadInt32())]; break; case OperandType.InlineField: MetadataToken field = new MetadataToken(br.ReadInt32()); switch (field.TokenType) { case TokenType.Field: instr.Operand = m_reflectReader.GetFieldDefAt(field.RID); break; case TokenType.MemberRef: instr.Operand = m_reflectReader.GetMemberRefAt(field.RID, context); break; default: throw new ReflectionException("Wrong token for InlineField Operand: " + field); } break; case OperandType.InlineMethod: MetadataToken meth = new MetadataToken(br.ReadInt32()); switch (meth.TokenType) { case TokenType.Method: instr.Operand = m_reflectReader.GetMethodDefAt(meth.RID); break; case TokenType.MemberRef: instr.Operand = m_reflectReader.GetMemberRefAt(meth.RID, context); break; case TokenType.MethodSpec: instr.Operand = m_reflectReader.GetMethodSpecAt(meth.RID, context); break; default: throw new ReflectionException("Wrong token for InlineMethod Operand: " + meth); } break; case OperandType.InlineType: MetadataToken type = new MetadataToken(br.ReadInt32()); switch (type.TokenType) { case TokenType.TypeDef: instr.Operand = m_reflectReader.GetTypeDefAt(type.RID); break; case TokenType.TypeRef: instr.Operand = m_reflectReader.GetTypeRefAt(type.RID); break; case TokenType.TypeSpec: instr.Operand = m_reflectReader.GetTypeSpecAt(type.RID, context); break; default: throw new ReflectionException("Wrong token for InlineType Operand: " + type); } break; case OperandType.InlineTok: MetadataToken token = new MetadataToken(br.ReadInt32()); switch (token.TokenType) { case TokenType.TypeDef: instr.Operand = m_reflectReader.GetTypeDefAt(token.RID); break; case TokenType.TypeRef: instr.Operand = m_reflectReader.GetTypeRefAt(token.RID); break; case TokenType.TypeSpec: instr.Operand = m_reflectReader.GetTypeSpecAt(token.RID, context); break; case TokenType.Field: instr.Operand = m_reflectReader.GetFieldDefAt(token.RID); break; case TokenType.Method: instr.Operand = m_reflectReader.GetMethodDefAt(token.RID); break; case TokenType.MethodSpec: instr.Operand = m_reflectReader.GetMethodSpecAt(token.RID, context); break; case TokenType.MemberRef: instr.Operand = m_reflectReader.GetMemberRefAt(token.RID, context); break; default: throw new ReflectionException("Wrong token following ldtoken: " + token); } break; } instructions.Add(instr.Offset, instr); if (last != null) { last.Next = instr; instr.Previous = last; } last = instr; code.Add(instr); } // resolve branches foreach (Instruction i in code) { switch (i.OpCode.OperandType) { case OperandType.ShortInlineBrTarget: case OperandType.InlineBrTarget: i.Operand = GetInstruction(body, instructions, (int)i.Operand); break; case OperandType.InlineSwitch: int [] lbls = (int [])i.Operand; Instruction [] instrs = new Instruction [lbls.Length]; for (int j = 0; j < lbls.Length; j++) { instrs [j] = GetInstruction(body, instructions, lbls [j]); } i.Operand = instrs; break; } } }
static void ComputeMaxStack(InstructionCollection instructions) { InstructionCollection ehs = new InstructionCollection (null); foreach (ExceptionHandler eh in instructions.Container.ExceptionHandlers) { switch (eh.Type) { case ExceptionHandlerType.Catch : ehs.Add (eh.HandlerStart); break; case ExceptionHandlerType.Filter : ehs.Add (eh.FilterStart); break; } } int max = 0; foreach (Instruction instr in instructions) { if (ehs.Contains (instr)) max++; switch (instr.OpCode.StackBehaviourPush) { case StackBehaviour.Push1: case StackBehaviour.Pushi: case StackBehaviour.Pushi8: case StackBehaviour.Pushr4: case StackBehaviour.Pushr8: case StackBehaviour.Pushref: case StackBehaviour.Varpush: max++; break; case StackBehaviour.Push1_push1: max += 2; break; } if (instr.OpCode.OperandType == OperandType.InlineMethod) { IMethodSignature signature = instr.Operand as IMethodSignature; if (signature != null && signature.ReturnType.ReturnType.FullName != Constants.Void) max++; } } instructions.Container.MaxStack = max; }
public void VisitInstructionCollection(InstructionCollection instructions) { foreach (Instruction instruction in instructions) { //VisitLabel(instruction); VisitInstruction(instruction); } }
static int GetLength(Instruction start, Instruction end, InstructionCollection instructions) { Instruction last = instructions [instructions.Count - 1]; return (end == instructions.Outside ? last.Offset + last.GetSize () : end.Offset) - start.Offset; }
internal ILProcessor(MethodBody body) { this.body = body; this.instructions = (InstructionCollection)body.Instructions; }
static bool IsRangeFat(Instruction start, Instruction end, InstructionCollection instructions) { return GetLength (start, end, instructions) >= 256 || start.Offset >= 65536; }
public override void VisitInstructionCollection (InstructionCollection instructions) { MethodBody body = instructions.Container; long start = m_codeWriter.BaseStream.Position; ComputeMaxStack (instructions); foreach (Instruction instr in instructions) { instr.Offset = (int) (m_codeWriter.BaseStream.Position - start); if (instr.OpCode.Size == 1) m_codeWriter.Write (instr.OpCode.Op2); else { m_codeWriter.Write (instr.OpCode.Op1); m_codeWriter.Write (instr.OpCode.Op2); } if (instr.OpCode.OperandType != OperandType.InlineNone && instr.Operand == null) throw new ReflectionException ("OpCode {0} have null operand", instr.OpCode.Name); switch (instr.OpCode.OperandType) { case OperandType.InlineNone : break; case OperandType.InlineSwitch : Instruction [] targets = instr.Operand as Instruction []; for (int i = 0; i < targets.Length + 1; i++) m_codeWriter.Write ((uint) 0); break; case OperandType.ShortInlineBrTarget : m_codeWriter.Write ((byte) 0); break; case OperandType.InlineBrTarget : m_codeWriter.Write (0); break; case OperandType.ShortInlineI : if (instr.OpCode == OpCodes.Ldc_I4_S) m_codeWriter.Write ((sbyte) instr.Operand); else m_codeWriter.Write ((byte) instr.Operand); break; case OperandType.ShortInlineVar : m_codeWriter.Write ((byte) body.Variables.IndexOf ( (VariableDefinition) instr.Operand)); break; case OperandType.ShortInlineParam : m_codeWriter.Write ((byte) GetParameterIndex (body, (ParameterDefinition) instr.Operand)); break; case OperandType.InlineSig : throw new NotImplementedException (); case OperandType.InlineI : m_codeWriter.Write ((int) instr.Operand); break; case OperandType.InlineVar : m_codeWriter.Write ((short) body.Variables.IndexOf ( (VariableDefinition) instr.Operand)); break; case OperandType.InlineParam : m_codeWriter.Write ((short) GetParameterIndex ( body, (ParameterDefinition) instr.Operand)); break; case OperandType.InlineI8 : m_codeWriter.Write ((long) instr.Operand); break; case OperandType.ShortInlineR : m_codeWriter.Write ((float) instr.Operand); break; case OperandType.InlineR : m_codeWriter.Write ((double) instr.Operand); break; case OperandType.InlineString : WriteToken (new MetadataToken (TokenType.String, m_reflectWriter.MetadataWriter.AddUserString (instr.Operand as string))); break; case OperandType.InlineField : if (instr.Operand is FieldReference) WriteToken ((instr.Operand as FieldReference).MetadataToken); else throw new ReflectionException ("Wrong operand for InlineField: {0}", instr.Operand.GetType ().FullName); break; case OperandType.InlineMethod : if (instr.Operand is GenericInstanceMethod) WriteToken (m_reflectWriter.GetMethodSpecToken (instr.Operand as GenericInstanceMethod)); else if (instr.Operand is MethodReference) WriteToken ((instr.Operand as MethodReference).MetadataToken); else throw new ReflectionException ("Wrong operand for InlineMethod: {0}", instr.Operand.GetType ().FullName); break; case OperandType.InlineType : if (instr.Operand is TypeReference) WriteToken (m_reflectWriter.GetTypeDefOrRefToken ( instr.Operand as TypeReference)); else throw new ReflectionException ("Wrong operand for InlineType: {0}", instr.Operand.GetType ().FullName); break; case OperandType.InlineTok : if (instr.Operand is TypeReference) WriteToken (m_reflectWriter.GetTypeDefOrRefToken ( instr.Operand as TypeReference)); else if (instr.Operand is GenericInstanceMethod) WriteToken (m_reflectWriter.GetMethodSpecToken (instr.Operand as GenericInstanceMethod)); else if (instr.Operand is IMetadataTokenProvider) WriteToken ((instr.Operand as IMetadataTokenProvider).MetadataToken); else throw new ReflectionException ( string.Format ("Wrong operand for {0} OpCode: {1}", instr.OpCode.OperandType.ToString (), instr.Operand.GetType ().FullName)); break; } } // patch branches long pos = m_codeWriter.BaseStream.Position; foreach (Instruction instr in instructions) { switch (instr.OpCode.OperandType) { case OperandType.InlineSwitch : m_codeWriter.BaseStream.Position = instr.Offset + instr.OpCode.Size; Instruction [] targets = instr.Operand as Instruction []; m_codeWriter.Write ((uint) targets.Length); foreach (Instruction tgt in targets) m_codeWriter.Write ((tgt.Offset - (instr.Offset + instr.OpCode.Size + (4 * (targets.Length + 1))))); break; case OperandType.ShortInlineBrTarget : m_codeWriter.BaseStream.Position = instr.Offset + instr.OpCode.Size; m_codeWriter.Write ((byte) ((instr.Operand as Instruction).Offset - (instr.Offset + instr.OpCode.Size + 1))); break; case OperandType.InlineBrTarget : m_codeWriter.BaseStream.Position = instr.Offset + instr.OpCode.Size; m_codeWriter.Write ((instr.Operand as Instruction).Offset - (instr.Offset + instr.OpCode.Size + 4)); break; } } m_codeWriter.BaseStream.Position = pos; }
void ReadCode() { start = position; var code_size = body.code_size; if (code_size < 0 || buffer.Length <= (uint) (code_size + position)) code_size = 0; var end = start + code_size; InstructionCollection instructions = new InstructionCollection (code_size / 3); body.instructions = instructions; instructions.initing = true; while (position < end) { var offset = base.position - start; var opcode = ReadOpCode (); var current = new Instruction (offset, opcode); current.index = instructions.Count; if (opcode.OperandType != OperandType.InlineNone) current.operand = ReadOperand (current); instructions.Add (current); } ResolveBranches (instructions); instructions.initing = false; }