zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

blob 10ea6508 (48980B) - Raw


      1 const std = @import("std");
      2 const builtin = @import("builtin");
      3 const fs = std.fs;
      4 const mem = std.mem;
      5 const json = std.json;
      6 const assert = std.debug.assert;
      7 
      8 // All references to other features are based on "zig name" as the key.
      9 
     10 const FeatureOverride = struct {
     11     llvm_name: []const u8,
     12     /// If true, completely omit the feature; as if it does not exist.
     13     omit: bool = false,
     14     /// If true, omit the feature, but all the dependencies of the feature
     15     /// are added in its place.
     16     flatten: bool = false,
     17     zig_name: ?[]const u8 = null,
     18     desc: ?[]const u8 = null,
     19     omit_deps: []const []const u8 = &.{},
     20     extra_deps: []const []const u8 = &.{},
     21 };
     22 
     23 const Cpu = struct {
     24     llvm_name: ?[]const u8,
     25     zig_name: []const u8,
     26     features: []const []const u8,
     27 };
     28 
     29 const Feature = struct {
     30     llvm_name: ?[]const u8 = null,
     31     zig_name: []const u8,
     32     desc: []const u8,
     33     deps: []const []const u8,
     34     flatten: bool = false,
     35 };
     36 
     37 const LlvmTarget = struct {
     38     zig_name: []const u8,
     39     llvm_name: []const u8,
     40     td_name: []const u8,
     41     feature_overrides: []const FeatureOverride = &.{},
     42     extra_cpus: []const Cpu = &.{},
     43     extra_features: []const Feature = &.{},
     44     omit_cpus: []const []const u8 = &.{},
     45     branch_quota: ?usize = null,
     46 };
     47 
     48 const llvm_targets = [_]LlvmTarget{
     49     .{
     50         .zig_name = "aarch64",
     51         .llvm_name = "AArch64",
     52         .td_name = "AArch64.td",
     53         .branch_quota = 2000,
     54         .feature_overrides = &.{
     55             .{
     56                 .llvm_name = "all",
     57                 .omit = true,
     58             },
     59             .{
     60                 .llvm_name = "v8a",
     61                 .extra_deps = &.{ "fp_armv8", "neon" },
     62             },
     63             .{
     64                 .llvm_name = "CONTEXTIDREL2",
     65                 .zig_name = "contextidr_el2",
     66                 .desc = "Enable RW operand Context ID Register (EL2)",
     67             },
     68             .{
     69                 .llvm_name = "neoversee1",
     70                 .flatten = true,
     71             },
     72             .{
     73                 .llvm_name = "neoversen1",
     74                 .flatten = true,
     75             },
     76             .{
     77                 .llvm_name = "neoversen2",
     78                 .flatten = true,
     79             },
     80             .{
     81                 .llvm_name = "neoversev1",
     82                 .flatten = true,
     83             },
     84             .{
     85                 .llvm_name = "neoversev2",
     86                 .flatten = true,
     87             },
     88             .{
     89                 .llvm_name = "neoverse512tvb",
     90                 .flatten = true,
     91             },
     92             .{
     93                 .llvm_name = "exynosm3",
     94                 .flatten = true,
     95                 .extra_deps = &.{"v8a"},
     96             },
     97             .{
     98                 .llvm_name = "exynosm4",
     99                 .flatten = true,
    100             },
    101             .{
    102                 .llvm_name = "v8.1a",
    103                 .extra_deps = &.{"v8a"},
    104             },
    105             .{
    106                 .llvm_name = "a35",
    107                 .flatten = true,
    108                 .extra_deps = &.{"v8a"},
    109             },
    110             .{
    111                 .llvm_name = "a53",
    112                 .flatten = true,
    113                 .extra_deps = &.{"v8a"},
    114             },
    115             .{
    116                 .llvm_name = "a55",
    117                 .flatten = true,
    118             },
    119             .{
    120                 .llvm_name = "a57",
    121                 .flatten = true,
    122                 .extra_deps = &.{"v8a"},
    123             },
    124             .{
    125                 .llvm_name = "a64fx",
    126                 .flatten = true,
    127             },
    128             .{
    129                 .llvm_name = "a72",
    130                 .flatten = true,
    131                 .extra_deps = &.{"v8a"},
    132             },
    133             .{
    134                 .llvm_name = "a73",
    135                 .flatten = true,
    136                 .extra_deps = &.{"v8a"},
    137             },
    138             .{
    139                 .llvm_name = "a75",
    140                 .flatten = true,
    141             },
    142             .{
    143                 .llvm_name = "a77",
    144                 .flatten = true,
    145             },
    146             .{
    147                 .llvm_name = "a715",
    148                 .flatten = true,
    149             },
    150             .{
    151                 .llvm_name = "ampere1a",
    152                 .flatten = true,
    153             },
    154             .{
    155                 .llvm_name = "apple-a7",
    156                 .flatten = true,
    157             },
    158             .{
    159                 .llvm_name = "apple-a10",
    160                 .flatten = true,
    161             },
    162             .{
    163                 .llvm_name = "apple-a11",
    164                 .flatten = true,
    165             },
    166             .{
    167                 .llvm_name = "apple-a12",
    168                 .flatten = true,
    169             },
    170             .{
    171                 .llvm_name = "apple-a13",
    172                 .flatten = true,
    173             },
    174             .{
    175                 .llvm_name = "apple-a14",
    176                 .flatten = true,
    177             },
    178             .{
    179                 .llvm_name = "apple-a15",
    180                 .flatten = true,
    181             },
    182             .{
    183                 .llvm_name = "apple-a16",
    184                 .flatten = true,
    185             },
    186             .{
    187                 .llvm_name = "apple-a17",
    188                 .flatten = true,
    189             },
    190             .{
    191                 .llvm_name = "apple-a7-sysreg",
    192                 .flatten = true,
    193             },
    194             .{
    195                 .llvm_name = "carmel",
    196                 .flatten = true,
    197             },
    198             .{
    199                 .llvm_name = "cortex-a78",
    200                 .flatten = true,
    201             },
    202             .{
    203                 .llvm_name = "cortex-x1",
    204                 .flatten = true,
    205             },
    206             .{
    207                 .llvm_name = "cortex-x2",
    208                 .flatten = true,
    209             },
    210             .{
    211                 .llvm_name = "cortex-x3",
    212                 .flatten = true,
    213             },
    214             .{
    215                 .llvm_name = "cortex-x4",
    216                 .flatten = true,
    217             },
    218             .{
    219                 .llvm_name = "falkor",
    220                 .flatten = true,
    221                 .extra_deps = &.{"v8a"},
    222             },
    223             .{
    224                 .llvm_name = "kryo",
    225                 .flatten = true,
    226                 .extra_deps = &.{"v8a"},
    227             },
    228             .{
    229                 .llvm_name = "saphira",
    230                 .flatten = true,
    231             },
    232             .{
    233                 .llvm_name = "thunderx",
    234                 .flatten = true,
    235                 .extra_deps = &.{"v8a"},
    236             },
    237             .{
    238                 .llvm_name = "thunderx2t99",
    239                 .flatten = true,
    240             },
    241             .{
    242                 .llvm_name = "thunderx3t110",
    243                 .flatten = true,
    244             },
    245             .{
    246                 .llvm_name = "thunderxt81",
    247                 .flatten = true,
    248                 .extra_deps = &.{"v8a"},
    249             },
    250             .{
    251                 .llvm_name = "thunderxt83",
    252                 .flatten = true,
    253                 .extra_deps = &.{"v8a"},
    254             },
    255             .{
    256                 .llvm_name = "thunderxt88",
    257                 .flatten = true,
    258                 .extra_deps = &.{"v8a"},
    259             },
    260             .{
    261                 .llvm_name = "tsv110",
    262                 .flatten = true,
    263             },
    264             .{
    265                 .llvm_name = "ampere1",
    266                 .flatten = true,
    267             },
    268             .{
    269                 .llvm_name = "ampere1b",
    270                 .flatten = true,
    271             },
    272         },
    273         .extra_cpus = &.{
    274             .{
    275                 .llvm_name = null,
    276                 .zig_name = "exynos_m1",
    277                 .features = &.{
    278                     "crc",
    279                     "crypto",
    280                     "exynos_cheap_as_move",
    281                     "force_32bit_jump_tables",
    282                     "fuse_aes",
    283                     "perfmon",
    284                     "slow_misaligned_128store",
    285                     "slow_paired_128",
    286                     "use_postra_scheduler",
    287                     "use_reciprocal_square_root",
    288                     "v8a",
    289                 },
    290             },
    291             .{
    292                 .llvm_name = null,
    293                 .zig_name = "exynos_m2",
    294                 .features = &.{
    295                     "crc",
    296                     "crypto",
    297                     "exynos_cheap_as_move",
    298                     "force_32bit_jump_tables",
    299                     "fuse_aes",
    300                     "perfmon",
    301                     "slow_misaligned_128store",
    302                     "slow_paired_128",
    303                     "use_postra_scheduler",
    304                     "v8a",
    305                 },
    306             },
    307             .{
    308                 .llvm_name = null,
    309                 .zig_name = "xgene1",
    310                 .features = &.{
    311                     "fp_armv8",
    312                     "neon",
    313                     "perfmon",
    314                     "v8a",
    315                 },
    316             },
    317             .{
    318                 .llvm_name = null,
    319                 .zig_name = "emag",
    320                 .features = &.{
    321                     "crc",
    322                     "crypto",
    323                     "fp_armv8",
    324                     "neon",
    325                     "perfmon",
    326                     "v8a",
    327                 },
    328             },
    329         },
    330     },
    331     .{
    332         .zig_name = "amdgpu",
    333         .llvm_name = "AMDGPU",
    334         .td_name = "AMDGPU.td",
    335         .feature_overrides = &.{
    336             .{
    337                 .llvm_name = "DumpCode",
    338                 .omit = true,
    339             },
    340             .{
    341                 .llvm_name = "dumpcode",
    342                 .omit = true,
    343             },
    344             .{
    345                 .llvm_name = "enable-ds128",
    346                 .zig_name = "ds128",
    347             },
    348             .{
    349                 .llvm_name = "enable-flat-scratch",
    350                 .zig_name = "flat_scratch",
    351             },
    352             .{
    353                 .llvm_name = "enable-prt-strict-null",
    354                 .zig_name = "prt_strict_null",
    355             },
    356         },
    357     },
    358     .{
    359         .zig_name = "arc",
    360         .llvm_name = "ARC",
    361         .td_name = "ARC.td",
    362     },
    363     .{
    364         .zig_name = "arm",
    365         .llvm_name = "ARM",
    366         .td_name = "ARM.td",
    367         .branch_quota = 10000,
    368         .extra_cpus = &.{
    369             .{
    370                 .llvm_name = "generic",
    371                 .zig_name = "baseline",
    372                 .features = &.{"v7a"},
    373             },
    374             .{
    375                 .llvm_name = null,
    376                 .zig_name = "exynos_m1",
    377                 .features = &.{ "v8a", "exynos" },
    378             },
    379             .{
    380                 .llvm_name = null,
    381                 .zig_name = "exynos_m2",
    382                 .features = &.{ "v8a", "exynos" },
    383             },
    384         },
    385         .feature_overrides = &.{
    386             .{
    387                 .llvm_name = "cortex-a78",
    388                 .flatten = true,
    389             },
    390             .{
    391                 .llvm_name = "cortex-a710",
    392                 .flatten = true,
    393             },
    394             .{
    395                 .llvm_name = "cortex-m4",
    396                 .omit_deps = &.{"vfp4d16sp"},
    397             },
    398             .{
    399                 .llvm_name = "cortex-m7",
    400                 .omit_deps = &.{"fp_armv8d16"},
    401             },
    402             .{
    403                 .llvm_name = "cortex-m33",
    404                 .omit_deps = &.{ "fp_armv8d16sp", "dsp" },
    405             },
    406             .{
    407                 .llvm_name = "cortex-m35p",
    408                 .omit_deps = &.{ "fp_armv8d16sp", "dsp" },
    409             },
    410             .{
    411                 .llvm_name = "cortex-m55",
    412                 .omit_deps = &.{ "mve_fp", "fp_armv8d16" },
    413             },
    414             .{
    415                 .llvm_name = "cortex-m85",
    416                 .omit_deps = &.{ "mve_fp", "pacbti", "fp_armv8d16" },
    417                 .extra_deps = &.{"trustzone"},
    418             },
    419             .{
    420                 .llvm_name = "cortex-x1c",
    421                 .flatten = true,
    422             },
    423             .{
    424                 .llvm_name = "r5",
    425                 .flatten = true,
    426             },
    427             .{
    428                 .llvm_name = "r52",
    429                 .flatten = true,
    430             },
    431             .{
    432                 .llvm_name = "r7",
    433                 .flatten = true,
    434             },
    435             .{
    436                 .llvm_name = "m7",
    437                 .flatten = true,
    438             },
    439             .{
    440                 .llvm_name = "krait",
    441                 .flatten = true,
    442             },
    443             .{
    444                 .llvm_name = "kryo",
    445                 .flatten = true,
    446             },
    447             .{
    448                 .llvm_name = "cortex-x1",
    449                 .flatten = true,
    450             },
    451             .{
    452                 .llvm_name = "neoverse-v1",
    453                 .flatten = true,
    454             },
    455             .{
    456                 .llvm_name = "a5",
    457                 .flatten = true,
    458             },
    459             .{
    460                 .llvm_name = "a7",
    461                 .flatten = true,
    462             },
    463             .{
    464                 .llvm_name = "a8",
    465                 .flatten = true,
    466             },
    467             .{
    468                 .llvm_name = "a9",
    469                 .flatten = true,
    470             },
    471             .{
    472                 .llvm_name = "a12",
    473                 .flatten = true,
    474             },
    475             .{
    476                 .llvm_name = "a15",
    477                 .flatten = true,
    478             },
    479             .{
    480                 .llvm_name = "a17",
    481                 .flatten = true,
    482             },
    483             .{
    484                 .llvm_name = "a32",
    485                 .flatten = true,
    486             },
    487             .{
    488                 .llvm_name = "a35",
    489                 .flatten = true,
    490             },
    491             .{
    492                 .llvm_name = "a53",
    493                 .flatten = true,
    494             },
    495             .{
    496                 .llvm_name = "a55",
    497                 .flatten = true,
    498             },
    499             .{
    500                 .llvm_name = "a57",
    501                 .flatten = true,
    502             },
    503             .{
    504                 .llvm_name = "a72",
    505                 .flatten = true,
    506             },
    507             .{
    508                 .llvm_name = "a73",
    509                 .flatten = true,
    510             },
    511             .{
    512                 .llvm_name = "a75",
    513                 .flatten = true,
    514             },
    515             .{
    516                 .llvm_name = "a77",
    517                 .flatten = true,
    518             },
    519             .{
    520                 .llvm_name = "a78c",
    521                 .flatten = true,
    522             },
    523             .{
    524                 .llvm_name = "armv2",
    525                 .zig_name = "v2",
    526                 .extra_deps = &.{"strict_align"},
    527             },
    528             .{
    529                 .llvm_name = "armv2a",
    530                 .zig_name = "v2a",
    531                 .extra_deps = &.{"strict_align"},
    532             },
    533             .{
    534                 .llvm_name = "armv3",
    535                 .zig_name = "v3",
    536                 .extra_deps = &.{"strict_align"},
    537             },
    538             .{
    539                 .llvm_name = "armv3m",
    540                 .zig_name = "v3m",
    541                 .extra_deps = &.{"strict_align"},
    542             },
    543             .{
    544                 .llvm_name = "armv4",
    545                 .zig_name = "v4",
    546                 .extra_deps = &.{"strict_align"},
    547             },
    548             .{
    549                 .llvm_name = "armv4t",
    550                 .zig_name = "v4t",
    551                 .extra_deps = &.{"strict_align"},
    552             },
    553             .{
    554                 .llvm_name = "armv5t",
    555                 .zig_name = "v5t",
    556                 .extra_deps = &.{"strict_align"},
    557             },
    558             .{
    559                 .llvm_name = "armv5te",
    560                 .zig_name = "v5te",
    561                 .extra_deps = &.{"strict_align"},
    562             },
    563             .{
    564                 .llvm_name = "armv5tej",
    565                 .zig_name = "v5tej",
    566                 .extra_deps = &.{"strict_align"},
    567             },
    568             .{
    569                 .llvm_name = "armv6",
    570                 .zig_name = "v6",
    571             },
    572             .{
    573                 .llvm_name = "armv6-m",
    574                 .zig_name = "v6m",
    575             },
    576             .{
    577                 .llvm_name = "armv6j",
    578                 .zig_name = "v6j",
    579             },
    580             .{
    581                 .llvm_name = "armv6k",
    582                 .zig_name = "v6k",
    583             },
    584             .{
    585                 .llvm_name = "armv6kz",
    586                 .zig_name = "v6kz",
    587             },
    588             .{
    589                 .llvm_name = "armv6s-m",
    590                 .zig_name = "v6sm",
    591             },
    592             .{
    593                 .llvm_name = "armv6t2",
    594                 .zig_name = "v6t2",
    595             },
    596             .{
    597                 .llvm_name = "armv7-a",
    598                 .zig_name = "v7a",
    599             },
    600             .{
    601                 .llvm_name = "armv7-m",
    602                 .zig_name = "v7m",
    603             },
    604             .{
    605                 .llvm_name = "armv7-r",
    606                 .zig_name = "v7r",
    607             },
    608             .{
    609                 .llvm_name = "armv7e-m",
    610                 .zig_name = "v7em",
    611             },
    612             .{
    613                 .llvm_name = "armv7k",
    614                 .zig_name = "v7k",
    615             },
    616             .{
    617                 .llvm_name = "armv7s",
    618                 .zig_name = "v7s",
    619             },
    620             .{
    621                 .llvm_name = "armv7ve",
    622                 .zig_name = "v7ve",
    623             },
    624             .{
    625                 .llvm_name = "armv8.1-a",
    626                 .zig_name = "v8_1a",
    627             },
    628             .{
    629                 .llvm_name = "armv8.1-m.main",
    630                 .zig_name = "v8_1m_main",
    631             },
    632             .{
    633                 .llvm_name = "armv8.2-a",
    634                 .zig_name = "v8_2a",
    635             },
    636             .{
    637                 .llvm_name = "armv8.3-a",
    638                 .zig_name = "v8_3a",
    639             },
    640             .{
    641                 .llvm_name = "armv8.4-a",
    642                 .zig_name = "v8_4a",
    643             },
    644             .{
    645                 .llvm_name = "armv8.5-a",
    646                 .zig_name = "v8_5a",
    647             },
    648             .{
    649                 .llvm_name = "armv8.6-a",
    650                 .zig_name = "v8_6a",
    651             },
    652             .{
    653                 .llvm_name = "armv8.7-a",
    654                 .zig_name = "v8_7a",
    655             },
    656             .{
    657                 .llvm_name = "armv8.8-a",
    658                 .zig_name = "v8_8a",
    659             },
    660             .{
    661                 .llvm_name = "armv8.9-a",
    662                 .zig_name = "v8_9a",
    663             },
    664             .{
    665                 .llvm_name = "armv8-a",
    666                 .zig_name = "v8a",
    667             },
    668             .{
    669                 .llvm_name = "armv8-m.base",
    670                 .zig_name = "v8m",
    671             },
    672             .{
    673                 .llvm_name = "armv8-m.main",
    674                 .zig_name = "v8m_main",
    675             },
    676             .{
    677                 .llvm_name = "armv8-r",
    678                 .zig_name = "v8r",
    679             },
    680             .{
    681                 .llvm_name = "armv9.1-a",
    682                 .zig_name = "v9_1a",
    683             },
    684             .{
    685                 .llvm_name = "armv9.2-a",
    686                 .zig_name = "v9_2a",
    687             },
    688             .{
    689                 .llvm_name = "armv9.3-a",
    690                 .zig_name = "v9_3a",
    691             },
    692             .{
    693                 .llvm_name = "armv9.4-a",
    694                 .zig_name = "v9_4a",
    695             },
    696             .{
    697                 .llvm_name = "armv9.5-a",
    698                 .zig_name = "v9_5a",
    699             },
    700             .{
    701                 .llvm_name = "armv9-a",
    702                 .zig_name = "v9a",
    703             },
    704             .{
    705                 .llvm_name = "v4t",
    706                 .zig_name = "has_v4t",
    707             },
    708             .{
    709                 .llvm_name = "v5t",
    710                 .zig_name = "has_v5t",
    711             },
    712             .{
    713                 .llvm_name = "v5te",
    714                 .zig_name = "has_v5te",
    715             },
    716             .{
    717                 .llvm_name = "v6",
    718                 .zig_name = "has_v6",
    719             },
    720             .{
    721                 .llvm_name = "v6k",
    722                 .zig_name = "has_v6k",
    723             },
    724             .{
    725                 .llvm_name = "v6m",
    726                 .zig_name = "has_v6m",
    727             },
    728             .{
    729                 .llvm_name = "v6t2",
    730                 .zig_name = "has_v6t2",
    731             },
    732             .{
    733                 .llvm_name = "v7",
    734                 .zig_name = "has_v7",
    735             },
    736             .{
    737                 .llvm_name = "v7clrex",
    738                 .zig_name = "has_v7clrex",
    739             },
    740             .{
    741                 .llvm_name = "v8",
    742                 .zig_name = "has_v8",
    743             },
    744             .{
    745                 .llvm_name = "v8m",
    746                 .zig_name = "has_v8m",
    747             },
    748             .{
    749                 .llvm_name = "v8m.main",
    750                 .zig_name = "has_v8m_main",
    751             },
    752             .{
    753                 .llvm_name = "v8.1a",
    754                 .zig_name = "has_v8_1a",
    755             },
    756             .{
    757                 .llvm_name = "v8.1m.main",
    758                 .zig_name = "has_v8_1m_main",
    759             },
    760             .{
    761                 .llvm_name = "v8.2a",
    762                 .zig_name = "has_v8_2a",
    763             },
    764             .{
    765                 .llvm_name = "v8.3a",
    766                 .zig_name = "has_v8_3a",
    767             },
    768             .{
    769                 .llvm_name = "v8.4a",
    770                 .zig_name = "has_v8_4a",
    771             },
    772             .{
    773                 .llvm_name = "v8.5a",
    774                 .zig_name = "has_v8_5a",
    775             },
    776             .{
    777                 .llvm_name = "v8.6a",
    778                 .zig_name = "has_v8_6a",
    779             },
    780             .{
    781                 .llvm_name = "v8.7a",
    782                 .zig_name = "has_v8_7a",
    783             },
    784             .{
    785                 .llvm_name = "v8.8a",
    786                 .zig_name = "has_v8_8a",
    787             },
    788             .{
    789                 .llvm_name = "v8.9a",
    790                 .zig_name = "has_v8_9a",
    791             },
    792             .{
    793                 .llvm_name = "v9a",
    794                 .zig_name = "has_v9a",
    795             },
    796             .{
    797                 .llvm_name = "v9.1a",
    798                 .zig_name = "has_v9_1a",
    799             },
    800             .{
    801                 .llvm_name = "v9.2a",
    802                 .zig_name = "has_v9_2a",
    803             },
    804             .{
    805                 .llvm_name = "v9.3a",
    806                 .zig_name = "has_v9_3a",
    807             },
    808             .{
    809                 .llvm_name = "v9.4a",
    810                 .zig_name = "has_v9_4a",
    811             },
    812         },
    813         // LLVM removed support for v2 and v3 but zig wants to support targeting old hardware
    814         .extra_features = &.{
    815             .{
    816                 .zig_name = "v2",
    817                 .desc = "ARMv2 architecture",
    818                 .deps = &.{"strict_align"},
    819             },
    820             .{
    821                 .zig_name = "v2a",
    822                 .desc = "ARMv2a architecture",
    823                 .deps = &.{"strict_align"},
    824             },
    825             .{
    826                 .zig_name = "v3",
    827                 .desc = "ARMv3 architecture",
    828                 .deps = &.{"strict_align"},
    829             },
    830             .{
    831                 .zig_name = "v3m",
    832                 .desc = "ARMv3m architecture",
    833                 .deps = &.{"strict_align"},
    834             },
    835         },
    836     },
    837     .{
    838         .zig_name = "avr",
    839         .llvm_name = "AVR",
    840         .td_name = "AVR.td",
    841     },
    842     .{
    843         .zig_name = "bpf",
    844         .llvm_name = "BPF",
    845         .td_name = "BPF.td",
    846     },
    847     .{
    848         .zig_name = "csky",
    849         .llvm_name = "CSKY",
    850         .td_name = "CSKY.td",
    851     },
    852     .{
    853         .zig_name = "hexagon",
    854         .llvm_name = "Hexagon",
    855         .td_name = "Hexagon.td",
    856     },
    857     .{
    858         .zig_name = "lanai",
    859         .llvm_name = "Lanai",
    860         .td_name = "Lanai.td",
    861     },
    862     .{
    863         .zig_name = "loongarch",
    864         .llvm_name = "LoongArch",
    865         .td_name = "LoongArch.td",
    866     },
    867     .{
    868         .zig_name = "m68k",
    869         .llvm_name = "M68k",
    870         .td_name = "M68k.td",
    871     },
    872     .{
    873         .zig_name = "msp430",
    874         .llvm_name = "MSP430",
    875         .td_name = "MSP430.td",
    876     },
    877     .{
    878         .zig_name = "mips",
    879         .llvm_name = "Mips",
    880         .td_name = "Mips.td",
    881     },
    882     .{
    883         .zig_name = "nvptx",
    884         .llvm_name = "NVPTX",
    885         .td_name = "NVPTX.td",
    886     },
    887     .{
    888         .zig_name = "powerpc",
    889         .llvm_name = "PowerPC",
    890         .td_name = "PPC.td",
    891         .feature_overrides = &.{
    892             .{
    893                 .llvm_name = "ppc32",
    894                 .omit = true,
    895             },
    896         },
    897     },
    898     .{
    899         .zig_name = "riscv",
    900         .llvm_name = "RISCV",
    901         .td_name = "RISCV.td",
    902         .feature_overrides = &.{
    903             .{
    904                 .llvm_name = "sifive7",
    905                 .flatten = true,
    906             },
    907         },
    908         .extra_cpus = &.{
    909             .{
    910                 .llvm_name = null,
    911                 .zig_name = "baseline_rv32",
    912                 .features = &.{ "32bit", "a", "c", "d", "f", "m" },
    913             },
    914             .{
    915                 .llvm_name = null,
    916                 .zig_name = "baseline_rv64",
    917                 .features = &.{ "64bit", "a", "c", "d", "f", "m" },
    918             },
    919         },
    920     },
    921     .{
    922         .zig_name = "sparc",
    923         .llvm_name = "Sparc",
    924         .td_name = "Sparc.td",
    925     },
    926     // TODO: merge tools/update_spirv_features.zig into this script
    927     //.{
    928     //    .zig_name = "spirv",
    929     //    .llvm_name = "SPIRV",
    930     //    .td_name = "SPIRV.td",
    931     //},
    932     .{
    933         .zig_name = "s390x",
    934         .llvm_name = "SystemZ",
    935         .td_name = "SystemZ.td",
    936     },
    937     .{
    938         .zig_name = "ve",
    939         .llvm_name = "VE",
    940         .td_name = "VE.td",
    941     },
    942     .{
    943         .zig_name = "wasm",
    944         .llvm_name = "WebAssembly",
    945         .td_name = "WebAssembly.td",
    946     },
    947     .{
    948         .zig_name = "x86",
    949         .llvm_name = "X86",
    950         .td_name = "X86.td",
    951         .feature_overrides = &.{
    952             .{
    953                 .llvm_name = "64bit-mode",
    954                 .omit = true,
    955             },
    956             .{
    957                 .llvm_name = "lakemont",
    958                 .extra_deps = &.{"soft_float"},
    959             },
    960         },
    961         .omit_cpus = &.{
    962             // LLVM defines a bunch of dumb aliases with foreach loops in X86.td.
    963             "pentium_mmx",
    964             "pentium_pro",
    965             "pentium_ii",
    966             "pentium_3m",
    967             "pentium_iii_no_xmm_regs",
    968             "pentium_iii",
    969             "pentium_m",
    970             "pentium4m",
    971             "pentium_4",
    972             "pentium_4_sse3",
    973             "core_2_duo_ssse3",
    974             "core_2_duo_sse4_1",
    975             "atom_sse4_2",
    976             "goldmont_plus",
    977             "core_i7_sse4_2",
    978             "core_aes_pclmulqdq",
    979             "corei7-avx",
    980             "core_2nd_gen_avx",
    981             "core-avx-i",
    982             "core_3rd_gen_avx",
    983             "core-avx2",
    984             "core_4th_gen_avx",
    985             "core_4th_gen_avx_tsx",
    986             "core_5th_gen_avx",
    987             "core_5th_gen_avx_tsx",
    988             "mic_avx512",
    989             "skylake_avx512",
    990             "icelake_client",
    991             "icelake_server",
    992             "graniterapids_d",
    993         },
    994     },
    995     .{
    996         .zig_name = "xcore",
    997         .llvm_name = "XCore",
    998         .td_name = "XCore.td",
    999     },
   1000     .{
   1001         .zig_name = "xtensa",
   1002         .llvm_name = "Xtensa",
   1003         .td_name = "Xtensa.td",
   1004     },
   1005 };
   1006 
   1007 pub fn main() anyerror!void {
   1008     var arena_state = std.heap.ArenaAllocator.init(std.heap.page_allocator);
   1009     defer arena_state.deinit();
   1010     const arena = arena_state.allocator();
   1011 
   1012     const args = try std.process.argsAlloc(arena);
   1013     if (args.len <= 1) {
   1014         usageAndExit(std.io.getStdErr(), args[0], 1);
   1015     }
   1016     if (std.mem.eql(u8, args[1], "--help")) {
   1017         usageAndExit(std.io.getStdOut(), args[0], 0);
   1018     }
   1019     if (args.len < 4) {
   1020         usageAndExit(std.io.getStdErr(), args[0], 1);
   1021     }
   1022 
   1023     const llvm_tblgen_exe = args[1];
   1024     if (std.mem.startsWith(u8, llvm_tblgen_exe, "-")) {
   1025         usageAndExit(std.io.getStdErr(), args[0], 1);
   1026     }
   1027 
   1028     const llvm_src_root = args[2];
   1029     if (std.mem.startsWith(u8, llvm_src_root, "-")) {
   1030         usageAndExit(std.io.getStdErr(), args[0], 1);
   1031     }
   1032 
   1033     const zig_src_root = args[3];
   1034     if (std.mem.startsWith(u8, zig_src_root, "-")) {
   1035         usageAndExit(std.io.getStdErr(), args[0], 1);
   1036     }
   1037 
   1038     var zig_src_dir = try fs.cwd().openDir(zig_src_root, .{});
   1039     defer zig_src_dir.close();
   1040 
   1041     var progress = std.Progress{};
   1042     const root_progress = progress.start("", llvm_targets.len);
   1043     defer root_progress.end();
   1044 
   1045     if (builtin.single_threaded) {
   1046         for (llvm_targets) |llvm_target| {
   1047             try processOneTarget(Job{
   1048                 .llvm_tblgen_exe = llvm_tblgen_exe,
   1049                 .llvm_src_root = llvm_src_root,
   1050                 .zig_src_dir = zig_src_dir,
   1051                 .root_progress = root_progress,
   1052                 .llvm_target = llvm_target,
   1053             });
   1054         }
   1055     } else {
   1056         var threads = try arena.alloc(std.Thread, llvm_targets.len);
   1057         for (llvm_targets, 0..) |llvm_target, i| {
   1058             const job = Job{
   1059                 .llvm_tblgen_exe = llvm_tblgen_exe,
   1060                 .llvm_src_root = llvm_src_root,
   1061                 .zig_src_dir = zig_src_dir,
   1062                 .root_progress = root_progress,
   1063                 .llvm_target = llvm_target,
   1064             };
   1065             threads[i] = try std.Thread.spawn(.{}, processOneTarget, .{job});
   1066         }
   1067         for (threads) |thread| {
   1068             thread.join();
   1069         }
   1070     }
   1071 }
   1072 
   1073 const Job = struct {
   1074     llvm_tblgen_exe: []const u8,
   1075     llvm_src_root: []const u8,
   1076     zig_src_dir: std.fs.Dir,
   1077     root_progress: *std.Progress.Node,
   1078     llvm_target: LlvmTarget,
   1079 };
   1080 
   1081 fn processOneTarget(job: Job) anyerror!void {
   1082     const llvm_target = job.llvm_target;
   1083 
   1084     var arena_state = std.heap.ArenaAllocator.init(std.heap.page_allocator);
   1085     defer arena_state.deinit();
   1086     const arena = arena_state.allocator();
   1087 
   1088     var progress_node = job.root_progress.start(llvm_target.zig_name, 3);
   1089     progress_node.activate();
   1090     defer progress_node.end();
   1091 
   1092     var tblgen_progress = progress_node.start("invoke llvm-tblgen", 0);
   1093     tblgen_progress.activate();
   1094 
   1095     const child_args = [_][]const u8{
   1096         job.llvm_tblgen_exe,
   1097         "--dump-json",
   1098         try std.fmt.allocPrint(arena, "{s}/llvm/lib/Target/{s}/{s}", .{
   1099             job.llvm_src_root,
   1100             llvm_target.llvm_name,
   1101             llvm_target.td_name,
   1102         }),
   1103         try std.fmt.allocPrint(arena, "-I={s}/llvm/include", .{job.llvm_src_root}),
   1104         try std.fmt.allocPrint(arena, "-I={s}/llvm/lib/Target/{s}", .{
   1105             job.llvm_src_root, llvm_target.llvm_name,
   1106         }),
   1107     };
   1108 
   1109     const child_result = try std.ChildProcess.run(.{
   1110         .allocator = arena,
   1111         .argv = &child_args,
   1112         .max_output_bytes = 400 * 1024 * 1024,
   1113     });
   1114     tblgen_progress.end();
   1115     if (child_result.stderr.len != 0) {
   1116         std.debug.print("{s}\n", .{child_result.stderr});
   1117     }
   1118 
   1119     const json_text = switch (child_result.term) {
   1120         .Exited => |code| if (code == 0) child_result.stdout else {
   1121             std.debug.print("llvm-tblgen exited with code {d}\n", .{code});
   1122             std.process.exit(1);
   1123         },
   1124         else => {
   1125             std.debug.print("llvm-tblgen crashed\n", .{});
   1126             std.process.exit(1);
   1127         },
   1128     };
   1129 
   1130     var json_parse_progress = progress_node.start("parse JSON", 0);
   1131     json_parse_progress.activate();
   1132 
   1133     const parsed = try json.parseFromSlice(json.Value, arena, json_text, .{});
   1134     defer parsed.deinit();
   1135     const root_map = &parsed.value.object;
   1136     json_parse_progress.end();
   1137 
   1138     var render_progress = progress_node.start("render zig code", 0);
   1139     render_progress.activate();
   1140 
   1141     var features_table = std.StringHashMap(Feature).init(arena);
   1142     var all_features = std.ArrayList(Feature).init(arena);
   1143     var all_cpus = std.ArrayList(Cpu).init(arena);
   1144     {
   1145         var it = root_map.iterator();
   1146         root_it: while (it.next()) |kv| {
   1147             if (kv.key_ptr.len == 0) continue;
   1148             if (kv.key_ptr.*[0] == '!') continue;
   1149             if (kv.value_ptr.* != .object) continue;
   1150             if (hasSuperclass(&kv.value_ptr.object, "SubtargetFeature")) {
   1151                 const llvm_name = kv.value_ptr.object.get("Name").?.string;
   1152                 if (llvm_name.len == 0) continue;
   1153 
   1154                 var zig_name = try llvmNameToZigName(arena, llvm_name);
   1155                 var desc = kv.value_ptr.object.get("Desc").?.string;
   1156                 var deps = std.ArrayList([]const u8).init(arena);
   1157                 var omit = false;
   1158                 var flatten = false;
   1159                 var omit_deps: []const []const u8 = &.{};
   1160                 var extra_deps: []const []const u8 = &.{};
   1161                 for (llvm_target.feature_overrides) |feature_override| {
   1162                     if (mem.eql(u8, llvm_name, feature_override.llvm_name)) {
   1163                         if (feature_override.omit) {
   1164                             // Still put the feature into the table so that we can
   1165                             // expand dependencies for the feature overrides marked `flatten`.
   1166                             omit = true;
   1167                         }
   1168                         if (feature_override.flatten) {
   1169                             flatten = true;
   1170                         }
   1171                         if (feature_override.zig_name) |override_name| {
   1172                             zig_name = override_name;
   1173                         }
   1174                         if (feature_override.desc) |override_desc| {
   1175                             desc = override_desc;
   1176                         }
   1177                         omit_deps = feature_override.omit_deps;
   1178                         extra_deps = feature_override.extra_deps;
   1179                         break;
   1180                     }
   1181                 }
   1182                 const implies = kv.value_ptr.object.get("Implies").?.array;
   1183                 for (implies.items) |imply| {
   1184                     const other_key = imply.object.get("def").?.string;
   1185                     const other_obj = &root_map.getPtr(other_key).?.object;
   1186                     const other_llvm_name = other_obj.get("Name").?.string;
   1187                     const other_zig_name = (try llvmNameToZigNameOmit(
   1188                         arena,
   1189                         llvm_target,
   1190                         other_llvm_name,
   1191                     )) orelse continue;
   1192                     for (omit_deps) |omit_dep| {
   1193                         if (mem.eql(u8, other_zig_name, omit_dep)) break;
   1194                     } else {
   1195                         try deps.append(other_zig_name);
   1196                     }
   1197                 }
   1198                 for (extra_deps) |extra_dep| {
   1199                     try deps.append(extra_dep);
   1200                 }
   1201                 const feature: Feature = .{
   1202                     .llvm_name = llvm_name,
   1203                     .zig_name = zig_name,
   1204                     .desc = desc,
   1205                     .deps = deps.items,
   1206                     .flatten = flatten,
   1207                 };
   1208                 try features_table.put(zig_name, feature);
   1209                 if (!omit and !flatten) {
   1210                     try all_features.append(feature);
   1211                 }
   1212             }
   1213             if (hasSuperclass(&kv.value_ptr.object, "Processor")) {
   1214                 const llvm_name = kv.value_ptr.object.get("Name").?.string;
   1215                 if (llvm_name.len == 0) continue;
   1216                 const omitted = for (llvm_target.omit_cpus) |omit_cpu_name| {
   1217                     if (mem.eql(u8, omit_cpu_name, llvm_name)) break true;
   1218                 } else false;
   1219                 if (omitted) continue;
   1220 
   1221                 var zig_name = try llvmNameToZigName(arena, llvm_name);
   1222                 var deps = std.ArrayList([]const u8).init(arena);
   1223                 var omit_deps: []const []const u8 = &.{};
   1224                 var extra_deps: []const []const u8 = &.{};
   1225                 for (llvm_target.feature_overrides) |feature_override| {
   1226                     if (mem.eql(u8, llvm_name, feature_override.llvm_name)) {
   1227                         if (feature_override.omit) {
   1228                             continue :root_it;
   1229                         }
   1230                         if (feature_override.zig_name) |override_name| {
   1231                             zig_name = override_name;
   1232                         }
   1233                         omit_deps = feature_override.omit_deps;
   1234                         extra_deps = feature_override.extra_deps;
   1235                         break;
   1236                     }
   1237                 }
   1238                 const features = kv.value_ptr.object.get("Features").?.array;
   1239                 for (features.items) |feature| {
   1240                     const feature_key = feature.object.get("def").?.string;
   1241                     const feature_obj = &root_map.getPtr(feature_key).?.object;
   1242                     const feature_llvm_name = feature_obj.get("Name").?.string;
   1243                     if (feature_llvm_name.len == 0) continue;
   1244                     const feature_zig_name = (try llvmNameToZigNameOmit(
   1245                         arena,
   1246                         llvm_target,
   1247                         feature_llvm_name,
   1248                     )) orelse continue;
   1249                     for (omit_deps) |omit_dep| {
   1250                         if (mem.eql(u8, feature_zig_name, omit_dep)) break;
   1251                     } else {
   1252                         try deps.append(feature_zig_name);
   1253                     }
   1254                 }
   1255                 for (extra_deps) |extra_dep| {
   1256                     try deps.append(extra_dep);
   1257                 }
   1258                 const tune_features = kv.value_ptr.object.get("TuneFeatures").?.array;
   1259                 for (tune_features.items) |feature| {
   1260                     const feature_key = feature.object.get("def").?.string;
   1261                     const feature_obj = &root_map.getPtr(feature_key).?.object;
   1262                     const feature_llvm_name = feature_obj.get("Name").?.string;
   1263                     if (feature_llvm_name.len == 0) continue;
   1264                     const feature_zig_name = (try llvmNameToZigNameOmit(
   1265                         arena,
   1266                         llvm_target,
   1267                         feature_llvm_name,
   1268                     )) orelse continue;
   1269                     try deps.append(feature_zig_name);
   1270                 }
   1271                 for (llvm_target.feature_overrides) |feature_override| {
   1272                     if (mem.eql(u8, llvm_name, feature_override.llvm_name)) {
   1273                         if (feature_override.omit) {
   1274                             continue :root_it;
   1275                         }
   1276                         if (feature_override.zig_name) |override_name| {
   1277                             zig_name = override_name;
   1278                         }
   1279                         for (feature_override.extra_deps) |extra_dep| {
   1280                             try deps.append(extra_dep);
   1281                         }
   1282                         break;
   1283                     }
   1284                 }
   1285                 try all_cpus.append(.{
   1286                     .llvm_name = llvm_name,
   1287                     .zig_name = zig_name,
   1288                     .features = deps.items,
   1289                 });
   1290             }
   1291         }
   1292     }
   1293     for (llvm_target.extra_features) |extra_feature| {
   1294         try features_table.put(extra_feature.zig_name, extra_feature);
   1295         try all_features.append(extra_feature);
   1296     }
   1297     for (llvm_target.extra_cpus) |extra_cpu| {
   1298         try all_cpus.append(extra_cpu);
   1299     }
   1300     mem.sort(Feature, all_features.items, {}, featureLessThan);
   1301     mem.sort(Cpu, all_cpus.items, {}, cpuLessThan);
   1302 
   1303     const target_sub_path = try fs.path.join(arena, &.{ "lib", "std", "Target" });
   1304     var target_dir = try job.zig_src_dir.makeOpenPath(target_sub_path, .{});
   1305     defer target_dir.close();
   1306 
   1307     const zig_code_basename = try std.fmt.allocPrint(arena, "{s}.zig", .{llvm_target.zig_name});
   1308 
   1309     if (all_features.items.len == 0) {
   1310         // We represent this with an empty file.
   1311         try target_dir.deleteTree(zig_code_basename);
   1312         return;
   1313     }
   1314 
   1315     var zig_code_file = try target_dir.createFile(zig_code_basename, .{});
   1316     defer zig_code_file.close();
   1317 
   1318     var bw = std.io.bufferedWriter(zig_code_file.writer());
   1319     const w = bw.writer();
   1320 
   1321     try w.writeAll(
   1322         \\//! This file is auto-generated by tools/update_cpu_features.zig.
   1323         \\
   1324         \\const std = @import("../std.zig");
   1325         \\const CpuFeature = std.Target.Cpu.Feature;
   1326         \\const CpuModel = std.Target.Cpu.Model;
   1327         \\
   1328         \\pub const Feature = enum {
   1329         \\
   1330     );
   1331 
   1332     for (all_features.items) |feature| {
   1333         try w.print("    {p},\n", .{std.zig.fmtId(feature.zig_name)});
   1334     }
   1335 
   1336     try w.writeAll(
   1337         \\};
   1338         \\
   1339         \\pub const featureSet = CpuFeature.feature_set_fns(Feature).featureSet;
   1340         \\pub const featureSetHas = CpuFeature.feature_set_fns(Feature).featureSetHas;
   1341         \\pub const featureSetHasAny = CpuFeature.feature_set_fns(Feature).featureSetHasAny;
   1342         \\pub const featureSetHasAll = CpuFeature.feature_set_fns(Feature).featureSetHasAll;
   1343         \\
   1344         \\pub const all_features = blk: {
   1345         \\
   1346     );
   1347     if (llvm_target.branch_quota) |branch_quota| {
   1348         try w.print("    @setEvalBranchQuota({d});\n", .{branch_quota});
   1349     }
   1350     try w.writeAll(
   1351         \\    const len = @typeInfo(Feature).Enum.fields.len;
   1352         \\    std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
   1353         \\    var result: [len]CpuFeature = undefined;
   1354         \\
   1355     );
   1356 
   1357     for (all_features.items) |feature| {
   1358         if (feature.llvm_name) |llvm_name| {
   1359             try w.print(
   1360                 \\    result[@intFromEnum(Feature.{p_})] = .{{
   1361                 \\        .llvm_name = "{}",
   1362                 \\        .description = "{}",
   1363                 \\        .dependencies = featureSet(&[_]Feature{{
   1364             ,
   1365                 .{
   1366                     std.zig.fmtId(feature.zig_name),
   1367                     std.zig.fmtEscapes(llvm_name),
   1368                     std.zig.fmtEscapes(feature.desc),
   1369                 },
   1370             );
   1371         } else {
   1372             try w.print(
   1373                 \\    result[@intFromEnum(Feature.{p_})] = .{{
   1374                 \\        .llvm_name = null,
   1375                 \\        .description = "{}",
   1376                 \\        .dependencies = featureSet(&[_]Feature{{
   1377             ,
   1378                 .{
   1379                     std.zig.fmtId(feature.zig_name),
   1380                     std.zig.fmtEscapes(feature.desc),
   1381                 },
   1382             );
   1383         }
   1384         var deps_set = std.StringHashMap(void).init(arena);
   1385         for (feature.deps) |dep| {
   1386             try putDep(&deps_set, features_table, dep);
   1387         }
   1388         try pruneFeatures(arena, features_table, &deps_set);
   1389         var dependencies = std.ArrayList([]const u8).init(arena);
   1390         {
   1391             var it = deps_set.keyIterator();
   1392             while (it.next()) |key| {
   1393                 try dependencies.append(key.*);
   1394             }
   1395         }
   1396         mem.sort([]const u8, dependencies.items, {}, asciiLessThan);
   1397 
   1398         if (dependencies.items.len == 0) {
   1399             try w.writeAll(
   1400                 \\}),
   1401                 \\    };
   1402                 \\
   1403             );
   1404         } else {
   1405             try w.writeAll("\n");
   1406             for (dependencies.items) |dep| {
   1407                 try w.print("            .{p_},\n", .{std.zig.fmtId(dep)});
   1408             }
   1409             try w.writeAll(
   1410                 \\        }),
   1411                 \\    };
   1412                 \\
   1413             );
   1414         }
   1415     }
   1416     try w.writeAll(
   1417         \\    const ti = @typeInfo(Feature);
   1418         \\    for (&result, 0..) |*elem, i| {
   1419         \\        elem.index = i;
   1420         \\        elem.name = ti.Enum.fields[i].name;
   1421         \\    }
   1422         \\    break :blk result;
   1423         \\};
   1424         \\
   1425         \\pub const cpu = struct {
   1426         \\
   1427     );
   1428     for (all_cpus.items) |cpu| {
   1429         var deps_set = std.StringHashMap(void).init(arena);
   1430         for (cpu.features) |feature_zig_name| {
   1431             try putDep(&deps_set, features_table, feature_zig_name);
   1432         }
   1433         try pruneFeatures(arena, features_table, &deps_set);
   1434         var cpu_features = std.ArrayList([]const u8).init(arena);
   1435         {
   1436             var it = deps_set.keyIterator();
   1437             while (it.next()) |key| {
   1438                 try cpu_features.append(key.*);
   1439             }
   1440         }
   1441         mem.sort([]const u8, cpu_features.items, {}, asciiLessThan);
   1442         if (cpu.llvm_name) |llvm_name| {
   1443             try w.print(
   1444                 \\    pub const {} = CpuModel{{
   1445                 \\        .name = "{}",
   1446                 \\        .llvm_name = "{}",
   1447                 \\        .features = featureSet(&[_]Feature{{
   1448             , .{
   1449                 std.zig.fmtId(cpu.zig_name),
   1450                 std.zig.fmtEscapes(cpu.zig_name),
   1451                 std.zig.fmtEscapes(llvm_name),
   1452             });
   1453         } else {
   1454             try w.print(
   1455                 \\    pub const {} = CpuModel{{
   1456                 \\        .name = "{}",
   1457                 \\        .llvm_name = null,
   1458                 \\        .features = featureSet(&[_]Feature{{
   1459             , .{
   1460                 std.zig.fmtId(cpu.zig_name),
   1461                 std.zig.fmtEscapes(cpu.zig_name),
   1462             });
   1463         }
   1464         if (cpu_features.items.len == 0) {
   1465             try w.writeAll(
   1466                 \\}),
   1467                 \\    };
   1468                 \\
   1469             );
   1470         } else {
   1471             try w.writeAll("\n");
   1472             for (cpu_features.items) |feature_zig_name| {
   1473                 try w.print("            .{p_},\n", .{std.zig.fmtId(feature_zig_name)});
   1474             }
   1475             try w.writeAll(
   1476                 \\        }),
   1477                 \\    };
   1478                 \\
   1479             );
   1480         }
   1481     }
   1482 
   1483     try w.writeAll(
   1484         \\};
   1485         \\
   1486     );
   1487     try bw.flush();
   1488 
   1489     render_progress.end();
   1490 }
   1491 
   1492 fn usageAndExit(file: fs.File, arg0: []const u8, code: u8) noreturn {
   1493     file.writer().print(
   1494         \\Usage: {s} /path/to/llvm-tblgen /path/git/llvm-project /path/git/zig
   1495         \\
   1496         \\Updates lib/std/target/<target>.zig from llvm/lib/Target/<Target>/<Target>.td .
   1497         \\
   1498         \\On a less beefy system, or when debugging, compile with -fsingle-threaded.
   1499         \\
   1500     , .{arg0}) catch std.process.exit(1);
   1501     std.process.exit(code);
   1502 }
   1503 
   1504 fn featureLessThan(context: void, a: Feature, b: Feature) bool {
   1505     _ = context;
   1506     return std.ascii.lessThanIgnoreCase(a.zig_name, b.zig_name);
   1507 }
   1508 
   1509 fn cpuLessThan(context: void, a: Cpu, b: Cpu) bool {
   1510     _ = context;
   1511     return std.ascii.lessThanIgnoreCase(a.zig_name, b.zig_name);
   1512 }
   1513 
   1514 fn asciiLessThan(context: void, a: []const u8, b: []const u8) bool {
   1515     _ = context;
   1516     return std.ascii.lessThanIgnoreCase(a, b);
   1517 }
   1518 
   1519 fn llvmNameToZigName(arena: mem.Allocator, llvm_name: []const u8) ![]const u8 {
   1520     const duped = try arena.dupe(u8, llvm_name);
   1521     for (duped) |*byte| switch (byte.*) {
   1522         '-', '.' => byte.* = '_',
   1523         else => continue,
   1524     };
   1525     return duped;
   1526 }
   1527 
   1528 fn llvmNameToZigNameOmit(
   1529     arena: mem.Allocator,
   1530     llvm_target: LlvmTarget,
   1531     llvm_name: []const u8,
   1532 ) !?[]const u8 {
   1533     for (llvm_target.feature_overrides) |feature_override| {
   1534         if (mem.eql(u8, feature_override.llvm_name, llvm_name)) {
   1535             if (feature_override.omit) return null;
   1536             return feature_override.zig_name orelse break;
   1537         }
   1538     }
   1539     return try llvmNameToZigName(arena, llvm_name);
   1540 }
   1541 
   1542 fn hasSuperclass(obj: *json.ObjectMap, class_name: []const u8) bool {
   1543     const superclasses_json = obj.get("!superclasses") orelse return false;
   1544     for (superclasses_json.array.items) |superclass_json| {
   1545         const superclass = superclass_json.string;
   1546         if (std.mem.eql(u8, superclass, class_name)) {
   1547             return true;
   1548         }
   1549     }
   1550     return false;
   1551 }
   1552 
   1553 fn pruneFeatures(
   1554     arena: mem.Allocator,
   1555     features_table: std.StringHashMap(Feature),
   1556     deps_set: *std.StringHashMap(void),
   1557 ) !void {
   1558     // For each element, recursively iterate over the dependencies and add
   1559     // everything we find to a "deletion set".
   1560     // Then, iterate over the deletion set and delete all that stuff from `deps_set`.
   1561     var deletion_set = std.StringHashMap(void).init(arena);
   1562     {
   1563         var it = deps_set.keyIterator();
   1564         while (it.next()) |key| {
   1565             const feature = features_table.get(key.*).?;
   1566             try walkFeatures(features_table, &deletion_set, feature);
   1567         }
   1568     }
   1569     {
   1570         var it = deletion_set.keyIterator();
   1571         while (it.next()) |key| {
   1572             _ = deps_set.remove(key.*);
   1573         }
   1574     }
   1575 }
   1576 
   1577 fn walkFeatures(
   1578     features_table: std.StringHashMap(Feature),
   1579     deletion_set: *std.StringHashMap(void),
   1580     feature: Feature,
   1581 ) error{OutOfMemory}!void {
   1582     for (feature.deps) |dep| {
   1583         try deletion_set.put(dep, {});
   1584         const other_feature = features_table.get(dep).?;
   1585         try walkFeatures(features_table, deletion_set, other_feature);
   1586     }
   1587 }
   1588 
   1589 fn putDep(
   1590     deps_set: *std.StringHashMap(void),
   1591     features_table: std.StringHashMap(Feature),
   1592     zig_feature_name: []const u8,
   1593 ) error{OutOfMemory}!void {
   1594     const feature = features_table.get(zig_feature_name).?;
   1595     if (feature.flatten) {
   1596         for (feature.deps) |dep| {
   1597             try putDep(deps_set, features_table, dep);
   1598         }
   1599     } else {
   1600         try deps_set.put(zig_feature_name, {});
   1601     }
   1602 }