Ejemplo n.º 1
0
 public override void VisitMethodBody(MethodBody body)
 {
     m_codeWriter.Empty();
 }
Ejemplo n.º 2
0
        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:
                case OperandType.InlineMethod:
                case OperandType.InlineType:
                case OperandType.InlineTok:
                    if (instr.Operand is TypeReference)
                    {
                        WriteToken(GetTypeToken((TypeReference)instr.Operand));
                    }
                    else if (instr.Operand is GenericInstanceMethod)
                    {
                        WriteToken(m_reflectWriter.GetMethodSpecToken(instr.Operand as GenericInstanceMethod));
                    }
                    else if (instr.Operand is MemberReference)
                    {
                        WriteToken(m_reflectWriter.GetMemberRefToken((MemberReference)instr.Operand));
                    }
                    else if (instr.Operand is IMetadataTokenProvider)
                    {
                        WriteToken(((IMetadataTokenProvider)instr.Operand).MetadataToken);
                    }
                    else
                    {
                        throw new ReflectionException(
                                  string.Format("Wrong operand for {0} OpCode: {1}",
                                                instr.OpCode.OperandType,
                                                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 = (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;
        }