public void Append(Instruction instr) { Instruction last = null, current = instr; if (m_instrs.Count > 0) { last = m_instrs [m_instrs.Count - 1]; } if (last != null) { last.Next = instr; current.Previous = last; } m_instrs.Add(current); }
void ReadCilBody(MethodBody body, BinaryReader br) { long start = br.BaseStream.Position; Instruction last = null; m_instructions.Clear(); InstructionCollection code = body.Instructions; 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: case OperandType.InlineMethod: case OperandType.InlineType: 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: " + token); } break; } m_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, (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, lbls [j]); } i.Operand = instrs; break; } } if (m_reflectReader.SymbolReader != null) { m_reflectReader.SymbolReader.Read(body, m_instructions); } }