protected void GetInstrDetails(ILInstruction instruction, 
            out string name, out Type declType, out string calledId)
        {
            name = null;
            declType = null;
            calledId = null;

            if (instruction.Operand is MethodInfo)
            {
                MethodInfo mOperand = (MethodInfo)instruction.Operand;
                declType = mOperand.DeclaringType;
                name = mOperand.Name;
                calledId = declType.FullName + " " + RefHelp.GetNameWithParameterList(mOperand);
            }
            else if (instruction.Operand is ConstructorInfo)
            {
                ConstructorInfo mOperand = (ConstructorInfo)instruction.Operand;
                declType = mOperand.DeclaringType;
                name = mOperand.Name;
                calledId = declType.FullName + " " + RefHelp.GetNameWithParameterList(mOperand);
            }
        }
        /// <summary>
        /// Constructs the array of ILInstructions according to the IL byte code.
        /// </summary>
        /// <param name="module"></param>
        private void ConstructInstructions(Module module)
        {
            byte[] il = this.il;
            int position = 0;
            instructions = new List<ILInstruction>();
            while (position < il.Length)
            {
                ILInstruction instruction = new ILInstruction();

                // get the operation code of the current instruction
                OpCode code = OpCodes.Nop;
                ushort value = il[position++];
                if (value != 0xfe)
                {
                    code = Globals.singleByteOpCodes[(int)value];
                }
                else
                {
                    value = il[position++];
                    code = Globals.multiByteOpCodes[(int)value];
                    value = (ushort)(value | 0xfe00);
                }
                instruction.Code = code;
                instruction.Offset = position - 1;
                int metadataToken = 0;
                // get the operand of the current operation
                switch (code.OperandType)
                {
                    case OperandType.InlineBrTarget:
                        metadataToken = ReadInt32(il, ref position);
                        metadataToken += position;
                        instruction.Operand = metadataToken;
                        break;

                    // patched from comments on CP -hwd
                    case OperandType.InlineField:
                        metadataToken = ReadInt32(il, ref position);
                        if (mi is ConstructorInfo)
                        {
                            instruction.Operand = module.ResolveField(metadataToken,
                                mi.DeclaringType.GetGenericArguments(), null);
                        }
                        else
                        {
                            instruction.Operand = module.ResolveField(metadataToken,
                                mi.DeclaringType.GetGenericArguments(), mi.GetGenericArguments());
                        }
                        break;

                    // patched from comments on CP -hwd
                    case OperandType.InlineMethod:
                        metadataToken = ReadInt32(il, ref position);
                        try
                        {
                            if (mi is ConstructorInfo)
                            {
                                instruction.Operand = module.ResolveMethod(metadataToken,
                                    mi.DeclaringType.GetGenericArguments(), null);
                            }
                            else
                            {
                                instruction.Operand = module.ResolveMethod(metadataToken,
                                    mi.DeclaringType.GetGenericArguments(), mi.GetGenericArguments());
                            }
                        }
                        catch
                        {
                            if (mi is ConstructorInfo)
                            {
                                instruction.Operand = module.ResolveMember(metadataToken,
                                    mi.DeclaringType.GetGenericArguments(), null);
                            }
                            else
                            {
                                instruction.Operand = module.ResolveMember(metadataToken,
                                    mi.DeclaringType.GetGenericArguments(), mi.GetGenericArguments());
                            }
                        }
                        break;

                    case OperandType.InlineSig:
                        metadataToken = ReadInt32(il, ref position);
                        instruction.Operand = module.ResolveSignature(metadataToken);
                        break;

                    // patched from comments on CP -hwd
                    case OperandType.InlineTok:
                        metadataToken = ReadInt32(il, ref position);
                        //try
                        //{
                            if (mi is ConstructorInfo)
                            {
                                instruction.Operand = module.ResolveType(metadataToken,
                                    mi.DeclaringType.GetGenericArguments(), null);
                            }
                            else
                            {
                                instruction.Operand = module.ResolveType(metadataToken,
                                    mi.DeclaringType.GetGenericArguments(), mi.GetGenericArguments());
                            }
                        //}
                        //catch
                        //{
                        //    int i = 1;

                        //}
                        break;

                    // patched from comments on CP -hwd
                    case OperandType.InlineType:
                        metadataToken = ReadInt32(il, ref position);
                        if (this.mi is MethodInfo)
                        {
                            instruction.Operand = module.ResolveType(metadataToken,
                            this.mi.DeclaringType.GetGenericArguments(), this.mi.GetGenericArguments());
                        }
                        else if (mi is ConstructorInfo)
                        {
                            instruction.Operand = module.ResolveType(metadataToken,
                               this.mi.DeclaringType.GetGenericArguments(), null);
                        }
                        else
                        {
                            instruction.Operand = module.ResolveType(metadataToken);
                        }
                        break;

                    case OperandType.InlineI:
                        {
                            instruction.Operand = ReadInt32(il, ref position);
                            break;
                        }
                    case OperandType.InlineI8:
                        {
                            instruction.Operand = ReadInt64(il, ref position);
                            break;
                        }
                    case OperandType.InlineNone:
                        {
                            instruction.Operand = null;
                            break;
                        }
                    case OperandType.InlineR:
                        {
                            instruction.Operand = ReadDouble(il, ref position);
                            break;
                        }
                    case OperandType.InlineString:
                        {
                            metadataToken = ReadInt32(il, ref position);
                            instruction.Operand = module.ResolveString(metadataToken);
                            break;
                        }
                    case OperandType.InlineSwitch:
                        {
                            int count = ReadInt32(il, ref position);
                            int[] casesAddresses = new int[count];
                            for (int i = 0; i < count; i++)
                            {
                                casesAddresses[i] = ReadInt32(il, ref position);
                            }
                            int[] cases = new int[count];
                            for (int i = 0; i < count; i++)
                            {
                                cases[i] = position + casesAddresses[i];
                            }
                            break;
                        }
                    case OperandType.InlineVar:
                        {
                            instruction.Operand = ReadUInt16(il, ref position);
                            break;
                        }
                    case OperandType.ShortInlineBrTarget:
                        {
                            instruction.Operand = ReadSByte(il, ref position) + position;
                            break;
                        }
                    case OperandType.ShortInlineI:
                        {
                            instruction.Operand = ReadSByte(il, ref position);
                            break;
                        }
                    case OperandType.ShortInlineR:
                        {
                            instruction.Operand = ReadSingle(il, ref position);
                            break;
                        }
                    case OperandType.ShortInlineVar:
                        {
                            instruction.Operand = ReadByte(il, ref position);
                            break;
                        }
                    default:
                        {
                            throw new Exception("Unknown operand type.");
                        }
                }
                instructions.Add(instruction);
            }
        }
        /// <summary>
        /// Constructs the array of ILInstructions according to the IL byte code.
        /// </summary>
        /// <param name="module"></param>
        private void ConstructInstructions(Module module)
        {
            byte[] il = this.il;
            int position = 0;
            instructions = new List<ILInstruction>();
            while (position < il.Length)
            {
                ILInstruction instruction = new ILInstruction();

                // get the operation code of the current instruction
                OpCode code = OpCodes.Nop;
                ushort value = il[position++];
                if (value != 0xfe)
                {
                    code = Globals.singleByteOpCodes[(int)value];
                }
                else
                {
                    value = il[position++];
                    code = Globals.multiByteOpCodes[(int)value];
                    value = (ushort)(value | 0xfe00);
                }
                instruction.Code = code;
                instruction.Offset = position - 1;
                int metadataToken = 0;
                // get the operand of the current operation
                switch (code.OperandType)
                {
                    case OperandType.InlineBrTarget:
                        metadataToken = ReadInt32(il, ref position);
                        metadataToken += position;
                        instruction.Operand = metadataToken;
                        break;
                    case OperandType.InlineField:
                        metadataToken = ReadInt32(il, ref position);
                        instruction.Operand = module.ResolveField(metadataToken);
                        break;
                    case OperandType.InlineMethod:
                        metadataToken = ReadInt32(il, ref position);
                        try
                        {
                            instruction.Operand = module.ResolveMethod(metadataToken);
                        }
                        catch
                        {
                            try
                            {
                                instruction.Operand = module.ResolveMember(metadataToken);
                            }
                            catch (Exception)
                            {
                                //Try generic method
                                try
                                {
                                    instruction.Operand = module.ResolveMethod(metadataToken, mi.DeclaringType.GetGenericArguments(), mi.GetGenericArguments());
                                }
                                catch (Exception)
                                {

                                    //Try generic member
                                    try
                                    {
                                        instruction.Operand = module.ResolveMember(metadataToken, mi.DeclaringType.GetGenericArguments(), mi.GetGenericArguments());
                                    }
                                    catch (Exception)
                                    {
                                        throw;
                                    }
                                }

                            }
                        }
                        break;
                    case OperandType.InlineSig:
                        metadataToken = ReadInt32(il, ref position);
                        instruction.Operand = module.ResolveSignature(metadataToken);
                        break;
                    case OperandType.InlineTok:
                        metadataToken = ReadInt32(il, ref position);
                        try
                        {
                            instruction.Operand = module.ResolveType(metadataToken);
                        }
                        catch
                        {

                        }
                        // SSS : see what to do here
                        break;
                     case OperandType.InlineType:
                        metadataToken = ReadInt32(il, ref position);
                        // now we call the ResolveType always using the generic attributes type in order
                        // to support decompilation of generic methods and classes

                        // thanks to the guys from code project who commented on this missing feature
                        try
                        {
                            instruction.Operand = module.ResolveType(metadataToken);
                        }
                        catch (Exception)
                        {
                            instruction.Operand = module.ResolveType(metadataToken, this.mi.DeclaringType.GetGenericArguments(), this.mi.GetGenericArguments());
                        }
                        break;
                    case OperandType.InlineI:
                        {
                            instruction.Operand = ReadInt32(il, ref position);
                            break;
                        }
                    case OperandType.InlineI8:
                        {
                            instruction.Operand = ReadInt64(il, ref position);
                            break;
                        }
                    case OperandType.InlineNone:
                        {
                            instruction.Operand = null;
                            break;
                        }
                    case OperandType.InlineR:
                        {
                            instruction.Operand = ReadDouble(il, ref position);
                            break;
                        }
                    case OperandType.InlineString:
                        {
                            metadataToken = ReadInt32(il, ref position);
                            instruction.Operand = module.ResolveString(metadataToken);
                            break;
                        }
                    case OperandType.InlineSwitch:
                        {
                            int count = ReadInt32(il, ref position);
                            int[] casesAddresses = new int[count];
                            for (int i = 0; i < count; i++)
                            {
                                casesAddresses[i] = ReadInt32(il, ref position);
                            }
                            int[] cases = new int[count];
                            for (int i = 0; i < count; i++)
                            {
                                cases[i] = position + casesAddresses[i];
                            }
                            break;
                        }
                    case OperandType.InlineVar:
                        {
                            instruction.Operand = ReadUInt16(il, ref position);
                            break;
                        }
                    case OperandType.ShortInlineBrTarget:
                        {
                            instruction.Operand = ReadSByte(il, ref position) + position;
                            break;
                        }
                    case OperandType.ShortInlineI:
                        {
                            instruction.Operand = ReadSByte(il, ref position);
                            break;
                        }
                    case OperandType.ShortInlineR:
                        {
                            instruction.Operand = ReadSingle(il, ref position);
                            break;
                        }
                    case OperandType.ShortInlineVar:
                        {
                            instruction.Operand = ReadByte(il, ref position);
                            break;
                        }
                    default:
                        {
                            throw new Exception("Unknown operand type.");
                        }
                }
                instructions.Add(instruction);
            }
        }
 /// <summary>
 /// Determines, how many operands a given CIL instruction will remove from the stack, and how many it will push onto the stack.
 /// </summary>
 /// <param name="ili">a CIL instruction</param>
 /// <param name="method">the method inside whose context the given instruction is executed</param>
 /// <param name="npop">number of removed stack operands</param>
 /// <param name="npush">number of stack operands pushed onto the stack</param>
 public static void GetStackBilance(ILInstruction ili, MethodBase method, out int npop, out int npush)
 {
     if (ili.Code.Equals(OpCodes.Ret))
     {
         Type returnType;
         if (method.IsFunction(out returnType))
             npop = 1;
         else
             npop = 0;
         npush = 0;
     }
     else if (ili.Code.Equals(OpCodes.Call) ||
         ili.Code.Equals(OpCodes.Calli) ||
         ili.Code.Equals(OpCodes.Callvirt) ||
         ili.Code.Equals(OpCodes.Newobj))
     {
         MethodBase mi = (MethodBase)ili.Operand;
         ParameterInfo[] pis = mi.GetParameters();
         npop = pis.Length;
         if (ili.Code.Equals(OpCodes.Calli))
             ++npop;
         if (mi.CallingConvention.HasFlag(CallingConventions.HasThis) &&
             !ili.Code.Equals(OpCodes.Newobj))
             ++npop;
         Type returnType;
         if (mi.IsFunction(out returnType) ||
             ili.Code.Equals(OpCodes.Newobj))
             npush = 1;
         else
             npush = 0;
     }
     else
     {
         npop = -StackOperands.GetNumOperands(ili.Code.StackBehaviourPop);
         npush = StackOperands.GetNumOperands(ili.Code.StackBehaviourPush);
     }
 }
        private static bool IsLdloc(ILInstruction cili, out int value)
        {
            if (cili.Code == OpCodes.Ldloc)
            {
                value = (int)cili.Operand;
                return true;
            }
            else if (cili.Code == OpCodes.Ldloc_S)
            {
                value = (byte)cili.Operand;
                return true;
            }
            else if (cili.Code == OpCodes.Ldloc_0)
            {
                value = 0;
                return true;
            }
            else if (cili.Code == OpCodes.Ldloc_1)
            {
                value = 1;
                return true;
            }
            else if (cili.Code == OpCodes.Ldloc_2)
            {
                value = 2;
                return true;
            }
            else if (cili.Code == OpCodes.Ldloc_3)
            {
                value = 3;
                return true;
            }

            value = int.MaxValue;
            return false;
        }
        private static bool IsLdc_I(ILInstruction cili, out int value)
        {
            if (cili.Code == OpCodes.Ldc_I4)
            {
                value = (int)cili.Operand;
                return true;
            }
            else if (cili.Code == OpCodes.Ldc_I4_0)
            {
                value = 0;
                return true;
            }
            else if (cili.Code == OpCodes.Ldc_I4_1)
            {
                value = 1;
                return true;
            }
            else if (cili.Code == OpCodes.Ldc_I4_2)
            {
                value = 2;
                return true;
            }
            else if (cili.Code == OpCodes.Ldc_I4_3)
            {
                value = 3;
                return true;
            }
            else if (cili.Code == OpCodes.Ldc_I4_4)
            {
                value = 4;
                return true;
            }
            else if (cili.Code == OpCodes.Ldc_I4_5)
            {
                value = 5;
                return true;
            }
            else if (cili.Code == OpCodes.Ldc_I4_6)
            {
                value = 6;
                return true;
            }
            else if (cili.Code == OpCodes.Ldc_I4_7)
            {
                value = 7;
                return true;
            }
            else if (cili.Code == OpCodes.Ldc_I4_8)
            {
                value = 8;
                return true;
            }
            else if (cili.Code == OpCodes.Ldc_I4_M1)
            {
                value = -1;
                return true;
            }
            else if (cili.Code == OpCodes.Ldc_I4_S)
            {
                value = (sbyte)cili.Operand;
                return true;
            }

            value = int.MaxValue;
            return false;
        }