Beispiel #1
0
 static uint GetFirstStringIndex(StringsTable stringsTable, object[] info, out bool hasVPrefix)
 {
     if (!(info[2] is string s))
     {
         throw new InvalidOperationException();
     }
     return(stringsTable.GetIndex(s, ignoreVPrefix: true, out hasVPrefix));
 }
        protected void SerializeTable(FileWriter writer, StringsTable stringsTable)
        {
            int index = -1;

            for (int i = 0; i < defs.Length; i++)
            {
                var def = defs[i];
                index++;
                var ctorKind = def.CtorKind;
                var code     = def.Code;
                if (code.Value != (uint)index)
                {
                    throw new InvalidOperationException();
                }

                if (index != 0)
                {
                    writer.WriteLine();
                }
                writer.WriteCommentLine(code.ToStringValue(idConverter));

                bool isSame = i > 0 && IsSame(defs[i - 1], def);
                if (isSame)
                {
                    ctorKind = previousCtorKind;
                }

                uint si = stringsTable.GetIndex(def.Mnemonic, ignoreVPrefix: true, out bool hasVPrefix);
                if (ctorKind.Value > 0x7F)
                {
                    throw new InvalidOperationException();
                }
                writer.WriteByte((byte)(ctorKind.Value | (hasVPrefix ? 0x80U : 0)));
                if (hasVPrefix)
                {
                    writer.WriteCommentLine($"'v', {ctorKind.ToStringValue(idConverter)}");
                }
                else
                {
                    writer.WriteCommentLine($"{ctorKind.ToStringValue(idConverter)}");
                }
                if (isSame)
                {
                    continue;
                }

                writer.WriteCompressedUInt32(si);
                writer.WriteCommentLine($"{si} = \"{def.Mnemonic}\"");
                foreach (var arg in def.Args)
                {
                    switch (arg)
                    {
                    case string s:
                        si = stringsTable.GetIndex(s, ignoreVPrefix: true, out hasVPrefix);
                        if (hasVPrefix)
                        {
                            throw new InvalidOperationException();
                        }
                        writer.WriteCompressedUInt32(si);
                        writer.WriteCommentLine($"{si} = \"{s}\"");
                        break;

                    case char c:
                        if ((ushort)c > byte.MaxValue)
                        {
                            throw new InvalidOperationException();
                        }
                        writer.WriteByte((byte)c);
                        if (c == '\0')
                        {
                            writer.WriteCommentLine(@"'\0'");
                        }
                        else
                        {
                            writer.WriteCommentLine($"'{c}'");
                        }
                        break;

                    case int ival:
                        writer.WriteCompressedUInt32((uint)ival);
                        writer.WriteCommentLine($"0x{ival:X}");
                        break;

                    case bool b:
                        writer.WriteByte((byte)(b ? 1 : 0));
                        writer.WriteCommentLine(b.ToString());
                        break;

                    case IEnumValue enumValue:
                        var typeId = enumValue.DeclaringType.TypeId;
                        if (typeId == TypeIds.GasInstrOpInfoFlags)
                        {
                            writer.WriteCompressedUInt32(enumValue.Value);
                            writer.WriteCommentLine($"0x{enumValue.Value:X} = {enumValue.ToStringValue(idConverter)}");
                        }
                        else if (typeId == TypeIds.IntelInstrOpInfoFlags)
                        {
                            writer.WriteCompressedUInt32(enumValue.Value);
                            writer.WriteCommentLine($"0x{enumValue.Value:X} = {enumValue.ToStringValue(idConverter)}");
                        }
                        else if (typeId == TypeIds.MasmInstrOpInfoFlags)
                        {
                            writer.WriteCompressedUInt32(enumValue.Value);
                            writer.WriteCommentLine($"0x{enumValue.Value:X} = {enumValue.ToStringValue(idConverter)}");
                        }
                        else if (typeId == TypeIds.NasmInstrOpInfoFlags)
                        {
                            writer.WriteCompressedUInt32(enumValue.Value);
                            writer.WriteCommentLine($"0x{enumValue.Value:X} = {enumValue.ToStringValue(idConverter)}");
                        }
                        else if (typeId == TypeIds.PseudoOpsKind)
                        {
                            if (enumValue.Value > byte.MaxValue)
                            {
                                throw new InvalidOperationException();
                            }
                            writer.WriteByte((byte)enumValue.Value);
                            writer.WriteCommentLine(enumValue.ToStringValue(idConverter));
                        }
                        else if (typeId == TypeIds.CodeSize)
                        {
                            if (enumValue.Value > byte.MaxValue)
                            {
                                throw new InvalidOperationException();
                            }
                            writer.WriteByte((byte)enumValue.Value);
                            writer.WriteCommentLine(enumValue.ToStringValue(idConverter));
                        }
                        else if (typeId == TypeIds.Register)
                        {
                            if (enumValue.Value > byte.MaxValue)
                            {
                                throw new InvalidOperationException();
                            }
                            writer.WriteByte((byte)enumValue.Value);
                            writer.WriteCommentLine(enumValue.ToStringValue(idConverter));
                        }
                        else if (typeId == TypeIds.MemorySize)
                        {
                            if (enumValue.Value > byte.MaxValue)
                            {
                                throw new InvalidOperationException();
                            }
                            writer.WriteByte((byte)enumValue.Value);
                            writer.WriteCommentLine(enumValue.ToStringValue(idConverter));
                        }
                        else if (typeId == TypeIds.NasmSignExtendInfo)
                        {
                            if (enumValue.Value > byte.MaxValue)
                            {
                                throw new InvalidOperationException();
                            }
                            writer.WriteByte((byte)enumValue.Value);
                            writer.WriteCommentLine(enumValue.ToStringValue(idConverter));
                        }
                        else
                        {
                            throw new InvalidOperationException();
                        }
                        break;

                    default:
                        throw new InvalidOperationException();
                    }
                }
            }
        }
        protected void SerializeTable(GenTypes genTypes, FileWriter writer, StringsTable stringsTable)
        {
            var fastFmtFlags   = genTypes[TypeIds.FastFmtFlags];
            var hasVPrefixEnum = fastFmtFlags[nameof(FastFmtFlags.HasVPrefix)];
            var sameAsPrevEnum = fastFmtFlags[nameof(FastFmtFlags.SameAsPrev)];

            var  flagsValues             = new List <EnumValue>();
            int  index                   = -1;
            uint prevMnemonicStringIndex = uint.MaxValue;

            foreach (var def in defs)
            {
                index++;
                var code = def.Code;
                if (code.Value != (uint)index)
                {
                    throw new InvalidOperationException();
                }
                flagsValues.Clear();

                if (index != 0)
                {
                    writer.WriteLine();
                }
                writer.WriteCommentLine(code.ToStringValue(idConverter));

                var  mnemonic            = def.Mnemonic;
                uint mnemonicStringIndex = stringsTable.GetIndex(mnemonic, ignoreVPrefix: true, out var hasVPrefix);
                var  flags = def.Flags;
                if (hasVPrefix)
                {
                    flagsValues.Add(hasVPrefixEnum);
                }
                bool isSame = false;
                if (mnemonicStringIndex == prevMnemonicStringIndex)
                {
                    isSame = true;
                    flagsValues.Add(sameAsPrevEnum);
                }

                if (def.Flags is EnumValue flags2)
                {
                    flagsValues.Add(flags2);
                }
                else if (def.Flags is OrEnumValue flags3)
                {
                    flagsValues.AddRange(flags3.Values);
                }
                else
                {
                    throw new InvalidOperationException();
                }

                uint flagsValue = 0;
                foreach (var enumValue in flagsValues)
                {
                    flagsValue |= enumValue.Value;
                }
                if (flagsValue > byte.MaxValue)
                {
                    throw new InvalidOperationException();
                }
                writer.WriteByte((byte)flagsValue);
                string comment = flagsValues.Count switch {
                    0 => "No flags set",
                    1 => flagsValues[0].ToStringValue(idConverter),
                    _ => new OrEnumValue(fastFmtFlags, flagsValues.ToArray()).ToStringValue(idConverter),
                };
                writer.WriteCommentLine(comment);

                // We save 4KB (11,595 -> 7,435 bytes)
                if (!isSame)
                {
                    writer.WriteCompressedUInt32(mnemonicStringIndex);
                    writer.WriteCommentLine($"{mnemonicStringIndex} = \"{mnemonic}\"");
                }

                prevMnemonicStringIndex = mnemonicStringIndex;
            }
        }
        protected void SerializeTable(GenTypes genTypes, FileWriter writer, StringsTable stringsTable)
        {
            var fastFmtFlags   = genTypes[TypeIds.FastFmtFlags];
            var hasVPrefixEnum = fastFmtFlags[nameof(FastFmtFlags.HasVPrefix)];
            var sameAsPrevEnum = fastFmtFlags[nameof(FastFmtFlags.SameAsPrev)];

            var  flagsValues             = new List <EnumValue>();
            int  index                   = -1;
            uint prevMnemonicStringIndex = uint.MaxValue;

            foreach (var info in infos)
            {
                if (info.Length < 2)
                {
                    throw new InvalidOperationException();
                }
                index++;
                var code = (EnumValue)info[0];
                if (code.Value != (uint)index)
                {
                    throw new InvalidOperationException();
                }
                flagsValues.Clear();

                if (index != 0)
                {
                    writer.WriteLine();
                }
                writer.WriteCommentLine(code.ToStringValue(idConverter));

                var  mnemonic            = info[1] as string ?? throw new InvalidOperationException();
                uint mnemonicStringIndex = stringsTable.GetIndex(mnemonic, ignoreVPrefix: true, out var hasVPrefix);
                if (hasVPrefix)
                {
                    flagsValues.Add(hasVPrefixEnum);
                }
                bool isSame = false;
                if (mnemonicStringIndex == prevMnemonicStringIndex)
                {
                    isSame = true;
                    flagsValues.Add(sameAsPrevEnum);
                }

                for (int i = 2; i < info.Length; i++)
                {
                    switch (info[i])
                    {
                    case IEnumValue enumValue:
                        var typeId = enumValue.DeclaringType.TypeId;
                        if (typeId == TypeIds.FastFmtFlags)
                        {
                            if (enumValue is EnumValue enumValue2)
                            {
                                flagsValues.Add(enumValue2);
                            }
                            else if (enumValue is OrEnumValue orEnumValue)
                            {
                                flagsValues.AddRange(orEnumValue.Values);
                            }
                            else
                            {
                                throw new InvalidOperationException();
                            }
                        }
                        else
                        {
                            throw new InvalidOperationException();
                        }
                        break;

                    default:
                        throw new InvalidOperationException();
                    }
                }

                uint flagsValue = 0;
                foreach (var enumValue in flagsValues)
                {
                    flagsValue |= enumValue.Value;
                }
                if (flagsValue > byte.MaxValue)
                {
                    throw new InvalidOperationException();
                }
                writer.WriteByte((byte)flagsValue);
                string comment;
                switch (flagsValues.Count)
                {
                case 0:
                    comment = "No flags set";
                    break;

                case 1:
                    comment = flagsValues[0].ToStringValue(idConverter);
                    break;

                default:
                    comment = new OrEnumValue(fastFmtFlags, flagsValues.ToArray()).ToStringValue(idConverter);
                    break;
                }
                writer.WriteCommentLine(comment);

                // We save 4KB (11,595 -> 7,435 bytes)
                if (!isSame)
                {
                    writer.WriteCompressedUInt32(mnemonicStringIndex);
                    writer.WriteCommentLine($"{mnemonicStringIndex} = \"{mnemonic}\"");
                }

                prevMnemonicStringIndex = mnemonicStringIndex;
            }
        }