Ejemplo n.º 1
0
        public static void Write(IAssemblyMetadata metadata, IReadOnlyList <Instruction> il)
        {
            for (var i = 0; i < il.Count; i++)
            {
                var opCode = il[i].OpCode;

                opCode.WriteOpCode(metadata.ILBuilder.WriteByte);

                switch (opCode.OperandType)
                {
                case OperandType.InlineNone:
                    break;

                case OperandType.InlineSwitch:
                    var branches = (int[])il[i].Operand;
                    metadata.ILBuilder.WriteInt32(branches.Length);
                    for (var k = 0; k < branches.Length; k++)
                    {
                        var branchOffset = branches[k];
                        metadata.ILBuilder.WriteInt32(branchOffset);
                    }

                    break;

                case OperandType.ShortInlineBrTarget:
                    var offset8 = (sbyte)il[i].Operand;
                    metadata.ILBuilder.WriteSByte(offset8);
                    break;

                case OperandType.InlineBrTarget:
                    var offset32 = (int)il[i].Operand;
                    // offset convention in IL: zero is at next instruction
                    metadata.ILBuilder.WriteInt32(offset32);
                    break;

                case OperandType.ShortInlineI:
                    if (opCode == OpCodes.Ldc_I4_S)
                    {
                        metadata.ILBuilder.WriteSByte((sbyte)il[i].Operand);
                    }
                    else
                    {
                        metadata.ILBuilder.WriteByte((byte)il[i].Operand);
                    }

                    break;

                case OperandType.InlineI:
                    metadata.ILBuilder.WriteInt32((int)il[i].Operand);
                    break;

                case OperandType.ShortInlineR:
                    metadata.ILBuilder.WriteSingle((float)il[i].Operand);
                    break;

                case OperandType.InlineR:
                    metadata.ILBuilder.WriteDouble((double)il[i].Operand);
                    break;

                case OperandType.InlineI8:
                    metadata.ILBuilder.WriteInt64((long)il[i].Operand);
                    break;

                case OperandType.InlineSig:
                    metadata.ILBuilder.WriteBytes((byte[])il[i].Operand);
                    break;

                case OperandType.InlineString:
                    metadata.ILBuilder.WriteInt32(
                        MetadataTokens.GetToken(metadata.GetOrAddUserString((string)il[i].Operand)));
                    break;

                case OperandType.InlineType:
                case OperandType.InlineTok:
                case OperandType.InlineMethod:
                case OperandType.InlineField:
                    switch (il[i].Operand)
                    {
                    case Type type:
                        metadata.ILBuilder.WriteInt32(MetadataTokens.GetToken(metadata.GetTypeHandle(type)));
                        break;

                    case ConstructorInfo constructorInfo:
                        metadata.ILBuilder.WriteInt32(
                            MetadataTokens.GetToken(metadata.GetConstructorHandle(constructorInfo)));
                        break;

                    case FieldInfo fieldInfo:
                        metadata.ILBuilder.WriteInt32(
                            MetadataTokens.GetToken(metadata.GetFieldHandle(fieldInfo)));
                        break;

                    case MethodInfo methodInfo:
                        metadata.ILBuilder.WriteInt32(
                            MetadataTokens.GetToken(metadata.GetMethodHandle(methodInfo)));
                        break;

                    default:
                        throw new NotSupportedException($"Unsupported inline operand: {il[i].Operand}");
                    }

                    break;

                case OperandType.ShortInlineVar:
                    var bLocalVariableInfo = il[i].Operand as LocalVariableInfo;
                    var bParameterInfo     = il[i].Operand as ParameterInfo;

                    if (bLocalVariableInfo != null)
                    {
                        metadata.ILBuilder.WriteByte((byte)bLocalVariableInfo.LocalIndex);
                    }
                    else if (bParameterInfo != null)
                    {
                        metadata.ILBuilder.WriteByte((byte)bParameterInfo.Position);
                    }
                    else
                    {
                        throw new NotSupportedException($"Unsupported short inline variable: {il[i].Operand}");
                    }

                    break;

                case OperandType.InlineVar:
                    var sLocalVariableInfo = il[i].Operand as LocalVariableInfo;
                    var sParameterInfo     = il[i].Operand as ParameterInfo;

                    if (sLocalVariableInfo != null)
                    {
                        metadata.ILBuilder.WriteUInt16((ushort)sLocalVariableInfo.LocalIndex);
                    }
                    else if (sParameterInfo != null)
                    {
                        metadata.ILBuilder.WriteUInt16((ushort)sParameterInfo.Position);
                    }
                    else
                    {
                        throw new NotSupportedException($"Unsupported inline variable: {il[i].Operand}");
                    }

                    break;

                default:
                    throw new NotSupportedException($"Unsupported operand type: {opCode.OperandType}");
                }
            }
        }