Esempio n. 1
0
 MetadataToken GetTypeToken(TypeReference type)
 {
     return(m_reflectWriter.GetTypeDefOrRefToken(type));
 }
Esempio 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.Parse(instr.Operand.ToString()));
                    }
                    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;
                }
            }

            // 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;
        }