1const builtin = @import("builtin");
2const spirv_spec = @import("spirv_spec");
3
4const std = @import("std");
5const Io = std.Io;
6const Dir = std.Io.Dir;
7const mem = std.mem;
8const json = std.json;
9const assert = std.debug.assert;
10
11// All references to other features are based on "zig name" as the key.
12
13const FeatureOverride = struct {
14 llvm_name: []const u8,
15 /// If true, completely omit the feature; as if it does not exist.
16 omit: bool = false,
17 /// If true, omit the feature, but all the dependencies of the feature
18 /// are added in its place.
19 flatten: bool = false,
20 zig_name: ?[]const u8 = null,
21 desc: ?[]const u8 = null,
22 omit_deps: []const []const u8 = &.{},
23 extra_deps: []const []const u8 = &.{},
24};
25
26const Cpu = struct {
27 llvm_name: ?[]const u8,
28 zig_name: []const u8,
29 features: []const []const u8,
30};
31
32const Feature = struct {
33 llvm_name: ?[]const u8 = null,
34 zig_name: []const u8,
35 desc: []const u8,
36 deps: []const []const u8,
37 flatten: bool = false,
38};
39
40const ArchTarget = struct {
41 zig_name: []const u8,
42 llvm: ?struct {
43 name: []const u8,
44 td_name: []const u8,
45 },
46 feature_overrides: []const FeatureOverride = &.{},
47 extra_cpus: []const Cpu = &.{},
48 extra_features: []const Feature = &.{},
49 omit_cpus: []const []const u8 = &.{},
50 branch_quota: ?usize = null,
51};
52
53const spirv_omitted_capabilities = [_][]const u8{
54 "shader", // implied by Vulkan/OpenGL targets
55 "kernel", // implied by OpenCL/AMDHSA targets
56 "addresses", // implied by OpenCL/AMDHSA targets
57 "physical_storage_buffer_addresses", // implied by spirv64-vulkan
58 "linkage", // automatically emitted when externs need linkage decorations
59};
60const spirv_omitted_extensions = [_][]const u8{
61 "SPV_KHR_physical_storage_buffer", // paired with physical_storage_buffer_addresses
62};
63
64const spirv_extra_features: []const Feature = blk: {
65 @setEvalBranchQuota(15_000);
66 var features: []const Feature = &.{};
67
68 cap: for (
69 @typeInfo(spirv_spec.Capability).@"enum".field_names,
70 @typeInfo(spirv_spec.Capability).@"enum".field_values,
71 ) |name, value| {
72 for (spirv_omitted_capabilities) |omitted| {
73 if (std.mem.eql(u8, omitted, name)) continue :cap;
74 }
75 features = features ++ &[_]Feature{.{
76 .zig_name = name,
77 .desc = "Enable " ++ name ++ " capability",
78 .deps = &struct {
79 const extensions = spirv_spec.Capability.dependencies(@fromBackingInt(@intCast(value)));
80 const deps: [extensions.len][]const u8 = inner: {
81 var out: [extensions.len][]const u8 = undefined;
82 for (extensions, 0..) |ext, i| out[i] = @tagName(ext);
83 break :inner out;
84 };
85 }.deps,
86 }};
87 }
88
89 ext: for (@typeInfo(spirv_spec.Extension).@"enum".field_names) |name| {
90 for (spirv_omitted_extensions) |omitted| {
91 if (std.mem.eql(u8, omitted, name)) continue :ext;
92 }
93 features = features ++ &[_]Feature{.{
94 .zig_name = name,
95 .desc = "Enable " ++ name ++ " extension",
96 .deps = if (std.mem.eql(u8, name, "v1_6"))
97 &.{"v1_5"}
98 else if (std.mem.eql(u8, name, "v1_5"))
99 &.{"v1_4"}
100 else if (std.mem.eql(u8, name, "v1_4"))
101 &.{"v1_3"}
102 else if (std.mem.eql(u8, name, "v1_3"))
103 &.{"v1_2"}
104 else if (std.mem.eql(u8, name, "v1_2"))
105 &.{"v1_1"}
106 else if (std.mem.eql(u8, name, "v1_1"))
107 &.{"v1_0"}
108 else
109 &.{},
110 }};
111 }
112
113 break :blk features;
114};
115
116const targets = [_]ArchTarget{
117 .{
118 .zig_name = "aarch64",
119 .llvm = .{
120 .name = "AArch64",
121 .td_name = "AArch64",
122 },
123 .branch_quota = 2000,
124 .feature_overrides = &.{
125 .{
126 .llvm_name = "all",
127 .omit = true,
128 },
129 .{
130 .llvm_name = "CONTEXTIDREL2",
131 .zig_name = "contextidr_el2",
132 .desc = "Enable RW operand Context ID Register (EL2)",
133 },
134 .{
135 .llvm_name = "neoversee1",
136 .flatten = true,
137 },
138 .{
139 .llvm_name = "neoversen1",
140 .flatten = true,
141 },
142 .{
143 .llvm_name = "neoversen2",
144 .flatten = true,
145 },
146 .{
147 .llvm_name = "neoversen3",
148 .flatten = true,
149 },
150 .{
151 .llvm_name = "neoversev1",
152 .flatten = true,
153 },
154 .{
155 .llvm_name = "neoversev2",
156 .flatten = true,
157 },
158 .{
159 .llvm_name = "neoversev3",
160 .flatten = true,
161 },
162 .{
163 .llvm_name = "neoversev3AE",
164 .flatten = true,
165 },
166 .{
167 .llvm_name = "neoverse512tvb",
168 .flatten = true,
169 },
170 .{
171 .llvm_name = "oryon-1",
172 .flatten = true,
173 },
174 .{
175 .llvm_name = "exynosm3",
176 .flatten = true,
177 },
178 .{
179 .llvm_name = "exynosm4",
180 .flatten = true,
181 },
182 .{
183 .llvm_name = "a35",
184 .flatten = true,
185 },
186 .{
187 .llvm_name = "a53",
188 .flatten = true,
189 },
190 .{
191 .llvm_name = "a55",
192 .flatten = true,
193 },
194 .{
195 .llvm_name = "a57",
196 .flatten = true,
197 },
198 .{
199 .llvm_name = "a510",
200 .flatten = true,
201 },
202 .{
203 .llvm_name = "a520",
204 .flatten = true,
205 },
206 .{
207 .llvm_name = "a520ae",
208 .flatten = true,
209 },
210 .{
211 .llvm_name = "a64fx",
212 .flatten = true,
213 },
214 .{
215 .llvm_name = "a65",
216 .flatten = true,
217 },
218 .{
219 .llvm_name = "a72",
220 .flatten = true,
221 },
222 .{
223 .llvm_name = "a73",
224 .flatten = true,
225 },
226 .{
227 .llvm_name = "a75",
228 .flatten = true,
229 },
230 .{
231 .llvm_name = "a76",
232 .flatten = true,
233 },
234 .{
235 .llvm_name = "a77",
236 .flatten = true,
237 },
238 .{
239 .llvm_name = "a78",
240 .flatten = true,
241 },
242 .{
243 .llvm_name = "a78ae",
244 .flatten = true,
245 },
246 .{
247 .llvm_name = "a78c",
248 .flatten = true,
249 },
250 .{
251 .llvm_name = "a710",
252 .flatten = true,
253 },
254 .{
255 .llvm_name = "a715",
256 .flatten = true,
257 },
258 .{
259 .llvm_name = "a720",
260 .flatten = true,
261 },
262 .{
263 .llvm_name = "a720ae",
264 .flatten = true,
265 },
266 .{
267 .llvm_name = "ampere1a",
268 .flatten = true,
269 },
270 .{
271 .llvm_name = "ampere1c",
272 .flatten = true,
273 },
274 .{
275 .llvm_name = "apple-a7",
276 .flatten = true,
277 },
278 .{
279 .llvm_name = "apple-a10",
280 .flatten = true,
281 },
282 .{
283 .llvm_name = "apple-a11",
284 .flatten = true,
285 },
286 .{
287 .llvm_name = "apple-a12",
288 .flatten = true,
289 },
290 .{
291 .llvm_name = "apple-a13",
292 .flatten = true,
293 },
294 .{
295 .llvm_name = "apple-a14",
296 .flatten = true,
297 },
298 .{
299 .llvm_name = "apple-a15",
300 .flatten = true,
301 },
302 .{
303 .llvm_name = "apple-a16",
304 .flatten = true,
305 },
306 .{
307 .llvm_name = "apple-a17",
308 .flatten = true,
309 },
310 .{
311 .llvm_name = "apple-a7-sysreg",
312 .flatten = true,
313 },
314 .{
315 .llvm_name = "apple-m4",
316 .flatten = true,
317 },
318 .{
319 .llvm_name = "apple-m5",
320 .flatten = true,
321 },
322 .{
323 .llvm_name = "c1-nano",
324 .flatten = true,
325 },
326 .{
327 .llvm_name = "c1-premium",
328 .flatten = true,
329 },
330 .{
331 .llvm_name = "c1-pro",
332 .flatten = true,
333 },
334 .{
335 .llvm_name = "c1-ultra",
336 .flatten = true,
337 },
338 .{
339 .llvm_name = "carmel",
340 .flatten = true,
341 },
342 .{
343 .llvm_name = "cortex-a725",
344 .flatten = true,
345 },
346 .{
347 .llvm_name = "cortex-a78",
348 .flatten = true,
349 },
350 .{
351 .llvm_name = "cortex-r82",
352 .flatten = true,
353 },
354 .{
355 .llvm_name = "cortex-r82ae",
356 .flatten = true,
357 },
358 .{
359 .llvm_name = "cortex-x1",
360 .flatten = true,
361 },
362 .{
363 .llvm_name = "cortex-x2",
364 .flatten = true,
365 },
366 .{
367 .llvm_name = "cortex-x3",
368 .flatten = true,
369 },
370 .{
371 .llvm_name = "cortex-x4",
372 .flatten = true,
373 },
374 .{
375 .llvm_name = "cortex-x925",
376 .flatten = true,
377 },
378 .{
379 .llvm_name = "falkor",
380 .flatten = true,
381 },
382 .{
383 .llvm_name = "kryo",
384 .flatten = true,
385 },
386 .{
387 .llvm_name = "saphira",
388 .flatten = true,
389 },
390 .{
391 .llvm_name = "thunderx",
392 .flatten = true,
393 },
394 .{
395 .llvm_name = "thunderx2t99",
396 .flatten = true,
397 },
398 .{
399 .llvm_name = "thunderx3t110",
400 .flatten = true,
401 },
402 .{
403 .llvm_name = "thunderxt81",
404 .flatten = true,
405 },
406 .{
407 .llvm_name = "thunderxt83",
408 .flatten = true,
409 },
410 .{
411 .llvm_name = "thunderxt88",
412 .flatten = true,
413 },
414 .{
415 .llvm_name = "tsv110",
416 .flatten = true,
417 },
418 .{
419 .llvm_name = "ampere1",
420 .flatten = true,
421 },
422 .{
423 .llvm_name = "ampere1b",
424 .flatten = true,
425 },
426 },
427 .extra_cpus = &.{
428 .{
429 .llvm_name = null,
430 .zig_name = "exynos_m1",
431 .features = &.{
432 "crc",
433 "crypto",
434 "exynos_cheap_as_move",
435 "force_32bit_jump_tables",
436 "fuse_aes",
437 "perfmon",
438 "slow_misaligned_128store",
439 "slow_paired_128",
440 "use_postra_scheduler",
441 "use_reciprocal_square_root",
442 "v8a",
443 },
444 },
445 .{
446 .llvm_name = null,
447 .zig_name = "exynos_m2",
448 .features = &.{
449 "crc",
450 "crypto",
451 "exynos_cheap_as_move",
452 "force_32bit_jump_tables",
453 "fuse_aes",
454 "perfmon",
455 "slow_misaligned_128store",
456 "slow_paired_128",
457 "use_postra_scheduler",
458 "v8a",
459 },
460 },
461 .{
462 .llvm_name = null,
463 .zig_name = "xgene1",
464 .features = &.{
465 "perfmon",
466 "v8a",
467 },
468 },
469 .{
470 .llvm_name = null,
471 .zig_name = "emag",
472 .features = &.{
473 "crc",
474 "crypto",
475 "perfmon",
476 "v8a",
477 },
478 },
479 },
480 .omit_cpus = &.{
481 // Who thought this alias was a good idea? Upgrade your compiler and suddenly your
482 // programs SIGILL because this changed meaning. Brilliant.
483 "apple-latest",
484 },
485 },
486 .{
487 .zig_name = "alpha",
488 .llvm = null,
489 .extra_features = &.{
490 .{
491 .zig_name = "bwx",
492 .desc = "Enable byte/word extensions",
493 .deps = &.{},
494 },
495 .{
496 .zig_name = "cix",
497 .desc = "Enable counting extensions",
498 .deps = &.{},
499 },
500 .{
501 .zig_name = "fix",
502 .desc = "Enable floating point move and square root extensions",
503 .deps = &.{},
504 },
505 .{
506 .zig_name = "max",
507 .desc = "Enable motion video extensions",
508 .deps = &.{},
509 },
510 },
511 .extra_cpus = &.{
512 .{
513 .llvm_name = null,
514 .zig_name = "ev4",
515 .features = &.{},
516 },
517 .{
518 .llvm_name = null,
519 .zig_name = "ev45",
520 .features = &.{},
521 },
522 .{
523 .llvm_name = null,
524 .zig_name = "ev5",
525 .features = &.{},
526 },
527 .{
528 .llvm_name = null,
529 .zig_name = "ev56",
530 .features = &.{
531 "bwx",
532 },
533 },
534 .{
535 .llvm_name = null,
536 .zig_name = "pca56",
537 .features = &.{
538 "bwx",
539 "max",
540 },
541 },
542 .{
543 .llvm_name = null,
544 .zig_name = "ev6",
545 .features = &.{
546 "bwx",
547 "fix",
548 "max",
549 },
550 },
551 .{
552 .llvm_name = null,
553 .zig_name = "ev67",
554 .features = &.{
555 "bwx",
556 "cix",
557 "fix",
558 "max",
559 },
560 },
561 },
562 },
563 .{
564 .zig_name = "amdgcn",
565 .llvm = .{
566 .name = "AMDGPU",
567 .td_name = "AMDGPU",
568 },
569 .branch_quota = 2000,
570 .feature_overrides = &.{
571 .{
572 .llvm_name = "DumpCode",
573 .omit = true,
574 },
575 .{
576 .llvm_name = "dumpcode",
577 .omit = true,
578 },
579 .{
580 .llvm_name = "enable-ds128",
581 .zig_name = "ds128",
582 },
583 .{
584 .llvm_name = "enable-flat-scratch",
585 .zig_name = "flat_scratch",
586 },
587 .{
588 .llvm_name = "enable-prt-strict-null",
589 .zig_name = "prt_strict_null",
590 },
591 },
592 },
593 .{
594 .zig_name = "arc",
595 .llvm = .{
596 .name = "ARC",
597 .td_name = "ARC",
598 },
599 },
600 .{
601 .zig_name = "arm",
602 .llvm = .{
603 .name = "ARM",
604 .td_name = "ARM",
605 },
606 .branch_quota = 10000,
607 .feature_overrides = &.{
608 .{
609 .llvm_name = "exynos",
610 .flatten = true,
611 },
612 .{
613 .llvm_name = "cortex-a78",
614 .flatten = true,
615 },
616 .{
617 .llvm_name = "cortex-a78ae",
618 .flatten = true,
619 },
620 .{
621 .llvm_name = "cortex-a710",
622 .flatten = true,
623 },
624 .{
625 .llvm_name = "cortex-m4",
626 .omit_deps = &.{"vfp4d16sp"},
627 },
628 .{
629 .llvm_name = "cortex-m7",
630 .omit_deps = &.{"fp_armv8d16"},
631 },
632 .{
633 .llvm_name = "cortex-m33",
634 .omit_deps = &.{ "fp_armv8d16sp", "dsp" },
635 },
636 .{
637 .llvm_name = "cortex-m35p",
638 .omit_deps = &.{ "fp_armv8d16sp", "dsp" },
639 },
640 .{
641 .llvm_name = "cortex-m55",
642 .omit_deps = &.{ "mve_fp", "fp_armv8d16" },
643 },
644 .{
645 .llvm_name = "cortex-m85",
646 .omit_deps = &.{ "mve_fp", "pacbti", "fp_armv8d16" },
647 },
648 .{
649 .llvm_name = "cortex-x1c",
650 .flatten = true,
651 },
652 .{
653 .llvm_name = "r4",
654 .flatten = true,
655 },
656 .{
657 .llvm_name = "r52plus",
658 .flatten = true,
659 },
660 .{
661 .llvm_name = "r5",
662 .flatten = true,
663 },
664 .{
665 .llvm_name = "r52",
666 .flatten = true,
667 },
668 .{
669 .llvm_name = "r7",
670 .flatten = true,
671 },
672 .{
673 .llvm_name = "m3",
674 .flatten = true,
675 },
676 .{
677 .llvm_name = "m7",
678 .flatten = true,
679 },
680 .{
681 .llvm_name = "krait",
682 .flatten = true,
683 },
684 .{
685 .llvm_name = "kryo",
686 .flatten = true,
687 },
688 .{
689 .llvm_name = "swift",
690 .flatten = true,
691 },
692 .{
693 .llvm_name = "cortex-x1",
694 .flatten = true,
695 },
696 .{
697 .llvm_name = "neoverse-v1",
698 .flatten = true,
699 },
700 .{
701 .llvm_name = "a5",
702 .flatten = true,
703 },
704 .{
705 .llvm_name = "a7",
706 .flatten = true,
707 },
708 .{
709 .llvm_name = "a8",
710 .flatten = true,
711 },
712 .{
713 .llvm_name = "a9",
714 .flatten = true,
715 },
716 .{
717 .llvm_name = "a12",
718 .flatten = true,
719 },
720 .{
721 .llvm_name = "a15",
722 .flatten = true,
723 },
724 .{
725 .llvm_name = "a17",
726 .flatten = true,
727 },
728 .{
729 .llvm_name = "a32",
730 .flatten = true,
731 },
732 .{
733 .llvm_name = "a35",
734 .flatten = true,
735 },
736 .{
737 .llvm_name = "a53",
738 .flatten = true,
739 },
740 .{
741 .llvm_name = "a55",
742 .flatten = true,
743 },
744 .{
745 .llvm_name = "a57",
746 .flatten = true,
747 },
748 .{
749 .llvm_name = "a72",
750 .flatten = true,
751 },
752 .{
753 .llvm_name = "a73",
754 .flatten = true,
755 },
756 .{
757 .llvm_name = "a75",
758 .flatten = true,
759 },
760 .{
761 .llvm_name = "a76",
762 .flatten = true,
763 },
764 .{
765 .llvm_name = "a77",
766 .flatten = true,
767 },
768 .{
769 .llvm_name = "a78c",
770 .flatten = true,
771 },
772 .{
773 .llvm_name = "armv2",
774 .zig_name = "v2",
775 .extra_deps = &.{"strict_align"},
776 },
777 .{
778 .llvm_name = "armv2a",
779 .zig_name = "v2a",
780 .extra_deps = &.{"strict_align"},
781 },
782 .{
783 .llvm_name = "armv3",
784 .zig_name = "v3",
785 .extra_deps = &.{"strict_align"},
786 },
787 .{
788 .llvm_name = "armv3m",
789 .zig_name = "v3m",
790 .extra_deps = &.{"strict_align"},
791 },
792 .{
793 .llvm_name = "armv4",
794 .zig_name = "v4",
795 .extra_deps = &.{"strict_align"},
796 },
797 .{
798 .llvm_name = "armv4t",
799 .zig_name = "v4t",
800 .extra_deps = &.{"strict_align"},
801 },
802 .{
803 .llvm_name = "armv5t",
804 .zig_name = "v5t",
805 .extra_deps = &.{"strict_align"},
806 },
807 .{
808 .llvm_name = "armv5te",
809 .zig_name = "v5te",
810 .extra_deps = &.{"strict_align"},
811 },
812 .{
813 .llvm_name = "armv5tej",
814 .zig_name = "v5tej",
815 .extra_deps = &.{"strict_align"},
816 },
817 .{
818 .llvm_name = "armv6",
819 .zig_name = "v6",
820 },
821 .{
822 .llvm_name = "armv6-m",
823 .zig_name = "v6m",
824 },
825 .{
826 .llvm_name = "armv6j",
827 .zig_name = "v6j",
828 },
829 .{
830 .llvm_name = "armv6k",
831 .zig_name = "v6k",
832 },
833 .{
834 .llvm_name = "armv6kz",
835 .zig_name = "v6kz",
836 },
837 .{
838 .llvm_name = "armv6s-m",
839 .zig_name = "v6sm",
840 },
841 .{
842 .llvm_name = "armv6t2",
843 .zig_name = "v6t2",
844 },
845 .{
846 .llvm_name = "armv7-a",
847 .zig_name = "v7a",
848 },
849 .{
850 .llvm_name = "armv7-m",
851 .zig_name = "v7m",
852 },
853 .{
854 .llvm_name = "armv7-r",
855 .zig_name = "v7r",
856 },
857 .{
858 .llvm_name = "armv7e-m",
859 .zig_name = "v7em",
860 },
861 .{
862 .llvm_name = "armv7k",
863 .omit = true,
864 },
865 .{
866 .llvm_name = "armv7s",
867 .omit = true,
868 },
869 .{
870 .llvm_name = "armv7ve",
871 .zig_name = "v7ve",
872 },
873 .{
874 .llvm_name = "armv8.1-a",
875 .zig_name = "v8_1a",
876 },
877 .{
878 .llvm_name = "armv8.1-m.main",
879 .zig_name = "v8_1m_main",
880 },
881 .{
882 .llvm_name = "armv8.2-a",
883 .zig_name = "v8_2a",
884 },
885 .{
886 .llvm_name = "armv8.3-a",
887 .zig_name = "v8_3a",
888 },
889 .{
890 .llvm_name = "armv8.4-a",
891 .zig_name = "v8_4a",
892 },
893 .{
894 .llvm_name = "armv8.5-a",
895 .zig_name = "v8_5a",
896 },
897 .{
898 .llvm_name = "armv8.6-a",
899 .zig_name = "v8_6a",
900 },
901 .{
902 .llvm_name = "armv8.7-a",
903 .zig_name = "v8_7a",
904 },
905 .{
906 .llvm_name = "armv8.8-a",
907 .zig_name = "v8_8a",
908 },
909 .{
910 .llvm_name = "armv8.9-a",
911 .zig_name = "v8_9a",
912 },
913 .{
914 .llvm_name = "armv8-a",
915 .zig_name = "v8a",
916 },
917 .{
918 .llvm_name = "armv8-m.base",
919 .zig_name = "v8m",
920 },
921 .{
922 .llvm_name = "armv8-m.main",
923 .zig_name = "v8m_main",
924 },
925 .{
926 .llvm_name = "armv8-r",
927 .zig_name = "v8r",
928 },
929 .{
930 .llvm_name = "armv9.1-a",
931 .zig_name = "v9_1a",
932 },
933 .{
934 .llvm_name = "armv9.2-a",
935 .zig_name = "v9_2a",
936 },
937 .{
938 .llvm_name = "armv9.3-a",
939 .zig_name = "v9_3a",
940 },
941 .{
942 .llvm_name = "armv9.4-a",
943 .zig_name = "v9_4a",
944 },
945 .{
946 .llvm_name = "armv9.5-a",
947 .zig_name = "v9_5a",
948 },
949 .{
950 .llvm_name = "armv9.6-a",
951 .zig_name = "v9_6a",
952 },
953 .{
954 .llvm_name = "armv9.7-a",
955 .zig_name = "v9_7a",
956 },
957 .{
958 .llvm_name = "armv9-a",
959 .zig_name = "v9a",
960 },
961 .{
962 .llvm_name = "v4t",
963 .zig_name = "has_v4t",
964 },
965 .{
966 .llvm_name = "v5t",
967 .zig_name = "has_v5t",
968 },
969 .{
970 .llvm_name = "v5te",
971 .zig_name = "has_v5te",
972 },
973 .{
974 .llvm_name = "v6",
975 .zig_name = "has_v6",
976 },
977 .{
978 .llvm_name = "v6k",
979 .zig_name = "has_v6k",
980 },
981 .{
982 .llvm_name = "v6m",
983 .zig_name = "has_v6m",
984 },
985 .{
986 .llvm_name = "v6t2",
987 .zig_name = "has_v6t2",
988 },
989 .{
990 .llvm_name = "v7",
991 .zig_name = "has_v7",
992 },
993 .{
994 .llvm_name = "v7clrex",
995 .zig_name = "has_v7clrex",
996 },
997 .{
998 .llvm_name = "v8",
999 .zig_name = "has_v8",
1000 },
1001 .{
1002 .llvm_name = "v8m",
1003 .zig_name = "has_v8m",
1004 },
1005 .{
1006 .llvm_name = "v8m.main",
1007 .zig_name = "has_v8m_main",
1008 },
1009 .{
1010 .llvm_name = "v8.1a",
1011 .zig_name = "has_v8_1a",
1012 },
1013 .{
1014 .llvm_name = "v8.1m.main",
1015 .zig_name = "has_v8_1m_main",
1016 },
1017 .{
1018 .llvm_name = "v8.2a",
1019 .zig_name = "has_v8_2a",
1020 },
1021 .{
1022 .llvm_name = "v8.3a",
1023 .zig_name = "has_v8_3a",
1024 },
1025 .{
1026 .llvm_name = "v8.4a",
1027 .zig_name = "has_v8_4a",
1028 },
1029 .{
1030 .llvm_name = "v8.5a",
1031 .zig_name = "has_v8_5a",
1032 },
1033 .{
1034 .llvm_name = "v8.6a",
1035 .zig_name = "has_v8_6a",
1036 },
1037 .{
1038 .llvm_name = "v8.7a",
1039 .zig_name = "has_v8_7a",
1040 },
1041 .{
1042 .llvm_name = "v8.8a",
1043 .zig_name = "has_v8_8a",
1044 },
1045 .{
1046 .llvm_name = "v8.9a",
1047 .zig_name = "has_v8_9a",
1048 },
1049 .{
1050 .llvm_name = "v9a",
1051 .zig_name = "has_v9a",
1052 },
1053 .{
1054 .llvm_name = "v9.1a",
1055 .zig_name = "has_v9_1a",
1056 },
1057 .{
1058 .llvm_name = "v9.2a",
1059 .zig_name = "has_v9_2a",
1060 },
1061 .{
1062 .llvm_name = "v9.3a",
1063 .zig_name = "has_v9_3a",
1064 },
1065 .{
1066 .llvm_name = "v9.4a",
1067 .zig_name = "has_v9_4a",
1068 },
1069 .{
1070 .llvm_name = "v9.5a",
1071 .zig_name = "has_v9_5a",
1072 },
1073 .{
1074 .llvm_name = "v9.6a",
1075 .zig_name = "has_v9_6a",
1076 },
1077 .{
1078 .llvm_name = "v9.7a",
1079 .zig_name = "has_v9_7a",
1080 },
1081 },
1082 .extra_cpus = &.{
1083 .{
1084 .llvm_name = "generic",
1085 .zig_name = "baseline",
1086 .features = &.{"v7a"},
1087 },
1088 .{
1089 .llvm_name = null,
1090 .zig_name = "exynos_m1",
1091 .features = &.{ "v8a", "exynos" },
1092 },
1093 .{
1094 .llvm_name = null,
1095 .zig_name = "exynos_m2",
1096 .features = &.{ "v8a", "exynos" },
1097 },
1098 },
1099 .extra_features = &.{
1100 // LLVM removed support for v2 and v3 but zig wants to support targeting old hardware
1101 .{
1102 .zig_name = "v2",
1103 .desc = "ARMv2 architecture",
1104 .deps = &.{"strict_align"},
1105 },
1106 .{
1107 .zig_name = "v2a",
1108 .desc = "ARMv2a architecture",
1109 .deps = &.{"strict_align"},
1110 },
1111 .{
1112 .zig_name = "v3",
1113 .desc = "ARMv3 architecture",
1114 .deps = &.{"strict_align"},
1115 },
1116 .{
1117 .zig_name = "v3m",
1118 .desc = "ARMv3m architecture",
1119 .deps = &.{"strict_align"},
1120 },
1121 },
1122 },
1123 .{
1124 .zig_name = "avr",
1125 .llvm = .{
1126 .name = "AVR",
1127 .td_name = "AVR",
1128 },
1129 },
1130 .{
1131 .zig_name = "bpf",
1132 .llvm = .{
1133 .name = "BPF",
1134 .td_name = "BPF",
1135 },
1136 },
1137 .{
1138 .zig_name = "csky",
1139 .llvm = .{
1140 .name = "CSKY",
1141 .td_name = "CSKY",
1142 },
1143 },
1144 .{
1145 .zig_name = "hexagon",
1146 .llvm = .{
1147 .name = "Hexagon",
1148 .td_name = "Hexagon",
1149 },
1150 },
1151 .{
1152 .zig_name = "hppa",
1153 .llvm = null,
1154 .extra_features = &.{
1155 .{
1156 .zig_name = "64bit",
1157 .desc = "Enable 64-bit PA-RISC 2.0",
1158 .deps = &.{"v2_0"},
1159 },
1160 .{
1161 .zig_name = "max_1",
1162 .desc = "Enable MAX-1 multimedia acceleration extensions",
1163 .deps = &.{},
1164 },
1165 .{
1166 .zig_name = "max_2",
1167 .desc = "Enable MAX-2 multimedia acceleration extensions",
1168 .deps = &.{"max_1"},
1169 },
1170 .{
1171 .zig_name = "v1_1",
1172 .desc = "Enable ISA v1.1",
1173 .deps = &.{},
1174 },
1175 .{
1176 .zig_name = "v2_0",
1177 .desc = "Enable ISA v2.0",
1178 .deps = &.{ "max_2", "v1_1" },
1179 },
1180 },
1181 .extra_cpus = &.{
1182 .{
1183 .llvm_name = null,
1184 .zig_name = "ts_1",
1185 .features = &.{},
1186 },
1187 .{
1188 .llvm_name = null,
1189 .zig_name = "ns_1",
1190 .features = &.{},
1191 },
1192 .{
1193 .llvm_name = null,
1194 .zig_name = "ns_2",
1195 .features = &.{},
1196 },
1197 .{
1198 .llvm_name = null,
1199 .zig_name = "pcx",
1200 .features = &.{},
1201 },
1202 .{
1203 .llvm_name = null,
1204 .zig_name = "pa_7000",
1205 .features = &.{
1206 "v1_1",
1207 },
1208 },
1209 .{
1210 .llvm_name = null,
1211 .zig_name = "pa_7100",
1212 .features = &.{
1213 "v1_1",
1214 },
1215 },
1216 .{
1217 .llvm_name = null,
1218 .zig_name = "pa_7150",
1219 .features = &.{
1220 "v1_1",
1221 },
1222 },
1223 .{
1224 .llvm_name = null,
1225 .zig_name = "pa_7100lc",
1226 .features = &.{
1227 "max_1",
1228 "v1_1",
1229 },
1230 },
1231 .{
1232 .llvm_name = null,
1233 .zig_name = "pa_7200",
1234 .features = &.{
1235 "v1_1",
1236 },
1237 },
1238 .{
1239 .llvm_name = null,
1240 .zig_name = "pa_7300lc",
1241 .features = &.{
1242 "max_1",
1243 "v1_1",
1244 },
1245 },
1246 .{
1247 .llvm_name = null,
1248 .zig_name = "pa_8000",
1249 .features = &.{
1250 "64bit",
1251 },
1252 },
1253 .{
1254 .llvm_name = null,
1255 .zig_name = "pa_8200",
1256 .features = &.{
1257 "64bit",
1258 },
1259 },
1260 .{
1261 .llvm_name = null,
1262 .zig_name = "pa_8500",
1263 .features = &.{
1264 "64bit",
1265 },
1266 },
1267 .{
1268 .llvm_name = null,
1269 .zig_name = "pa_8600",
1270 .features = &.{
1271 "64bit",
1272 },
1273 },
1274 .{
1275 .llvm_name = null,
1276 .zig_name = "pa_8700",
1277 .features = &.{
1278 "64bit",
1279 },
1280 },
1281 .{
1282 .llvm_name = null,
1283 .zig_name = "pa_8800",
1284 .features = &.{
1285 "64bit",
1286 },
1287 },
1288 .{
1289 .llvm_name = null,
1290 .zig_name = "pa_8900",
1291 .features = &.{
1292 "64bit",
1293 },
1294 },
1295 },
1296 },
1297 .{
1298 .zig_name = "kvx",
1299 .llvm = null,
1300 .extra_features = &.{
1301 .{
1302 .zig_name = "v3_1",
1303 .desc = "Enable ISA v3.1",
1304 .deps = &.{},
1305 },
1306 .{
1307 .zig_name = "v3_2",
1308 .desc = "Enable ISA v3.2",
1309 .deps = &.{"v3_1"},
1310 },
1311 .{
1312 .zig_name = "v4_1",
1313 .desc = "Enable ISA v4.1",
1314 .deps = &.{"v3_2"},
1315 },
1316 },
1317 .extra_cpus = &.{
1318 .{
1319 .llvm_name = null,
1320 .zig_name = "coolidge_v1",
1321 .features = &.{
1322 "v3_1",
1323 },
1324 },
1325 .{
1326 .llvm_name = null,
1327 .zig_name = "coolidge_v2",
1328 .features = &.{
1329 "v3_2",
1330 },
1331 },
1332 },
1333 },
1334 .{
1335 .zig_name = "lanai",
1336 .llvm = .{
1337 .name = "Lanai",
1338 .td_name = "Lanai",
1339 },
1340 },
1341 .{
1342 .zig_name = "loongarch",
1343 .llvm = .{
1344 .name = "LoongArch",
1345 .td_name = "LoongArch",
1346 },
1347 .extra_cpus = &.{
1348 .{
1349 .llvm_name = null,
1350 .zig_name = "generic_la64",
1351 .features = &.{
1352 "64bit",
1353 },
1354 },
1355 .{
1356 .llvm_name = null,
1357 .zig_name = "la32v1_0",
1358 .features = &.{
1359 "32bit",
1360 "32s",
1361 "d",
1362 "ual",
1363 },
1364 },
1365 .{
1366 .llvm_name = null,
1367 .zig_name = "la32rv1_0",
1368 .features = &.{
1369 "32bit",
1370 "ual",
1371 },
1372 },
1373 .{
1374 .llvm_name = null,
1375 .zig_name = "la64v1_0",
1376 .features = &.{
1377 "64bit",
1378 "lsx",
1379 "ual",
1380 },
1381 },
1382 .{
1383 .llvm_name = null,
1384 .zig_name = "la64v1_1",
1385 .features = &.{
1386 "64bit",
1387 "div32",
1388 "frecipe",
1389 "lam_bh",
1390 "lamcas",
1391 "ld_seq_sa",
1392 "lsx",
1393 "scq",
1394 "ual",
1395 },
1396 },
1397 },
1398 .omit_cpus = &.{
1399 "generic",
1400 "generic-la64",
1401 "loongarch32",
1402 "loongarch64",
1403 },
1404 },
1405 .{
1406 .zig_name = "m68k",
1407 .llvm = .{
1408 .name = "M68k",
1409 .td_name = "M68k",
1410 },
1411 },
1412 .{
1413 .zig_name = "msp430",
1414 .llvm = .{
1415 .name = "MSP430",
1416 .td_name = "MSP430",
1417 },
1418 },
1419 .{
1420 .zig_name = "mips",
1421 .llvm = .{
1422 .name = "Mips",
1423 .td_name = "Mips",
1424 },
1425 .extra_features = &.{
1426 .{
1427 .zig_name = "notraps",
1428 .desc = "Disable trap instructions",
1429 .deps = &.{},
1430 },
1431 },
1432 .extra_cpus = &.{
1433 .{
1434 .llvm_name = null,
1435 .zig_name = "r3000a",
1436 .features = &.{
1437 "mips1",
1438 "soft_float",
1439 "notraps",
1440 },
1441 },
1442 .{
1443 .llvm_name = null,
1444 .zig_name = "allegrex",
1445 .features = &.{ "mips2", "single_float", "notraps" },
1446 },
1447 },
1448 },
1449 .{
1450 .zig_name = "nvptx",
1451 .llvm = .{
1452 .name = "NVPTX",
1453 .td_name = "NVPTX",
1454 },
1455 },
1456 .{
1457 .zig_name = "powerpc",
1458 .llvm = .{
1459 .name = "PowerPC",
1460 .td_name = "PPC",
1461 },
1462 .feature_overrides = &.{
1463 .{
1464 .llvm_name = "aix",
1465 .omit = true,
1466 },
1467 .{
1468 .llvm_name = "aix-shared-lib-tls-model-opt",
1469 .omit = true,
1470 },
1471 .{
1472 .llvm_name = "aix-small-local-dynamic-tls",
1473 .omit = true,
1474 },
1475 .{
1476 .llvm_name = "aix-small-local-exec-tls",
1477 .omit = true,
1478 },
1479 .{
1480 .llvm_name = "modern-aix-as",
1481 .omit = true,
1482 },
1483 },
1484 .omit_cpus = &.{
1485 "ppc32",
1486 },
1487 },
1488 .{
1489 .zig_name = "propeller",
1490 .llvm = null,
1491 .extra_features = &.{
1492 .{
1493 .zig_name = "p2",
1494 .desc = "Enable Propeller 2",
1495 .deps = &.{},
1496 },
1497 },
1498 .extra_cpus = &.{
1499 .{
1500 .llvm_name = null,
1501 .zig_name = "p1",
1502 .features = &.{},
1503 },
1504 .{
1505 .llvm_name = null,
1506 .zig_name = "p2",
1507 .features = &.{"p2"},
1508 },
1509 },
1510 },
1511 .{
1512 .zig_name = "spirv",
1513 .llvm = .{
1514 .name = "SPIRV",
1515 .td_name = "SPIRV",
1516 },
1517 .branch_quota = 2000,
1518 .extra_features = spirv_extra_features,
1519 .extra_cpus = &.{
1520 .{
1521 .llvm_name = null,
1522 .zig_name = "vulkan_v1_2",
1523 .features = &.{"v1_5"},
1524 },
1525 .{
1526 .llvm_name = null,
1527 .zig_name = "opencl_v2",
1528 .features = &.{"v1_2"},
1529 },
1530 },
1531 },
1532 .{
1533 .zig_name = "riscv",
1534 .llvm = .{
1535 .name = "RISCV",
1536 .td_name = "RISCV",
1537 },
1538 .branch_quota = 2000,
1539 .feature_overrides = &.{
1540 .{
1541 .llvm_name = "sifive7",
1542 .flatten = true,
1543 },
1544 },
1545 .extra_cpus = &.{
1546 .{
1547 .llvm_name = null,
1548 .zig_name = "baseline_rv32",
1549 .features = &.{ "32bit", "a", "c", "d", "f", "i", "m" },
1550 },
1551 .{
1552 .llvm_name = null,
1553 .zig_name = "baseline_rv64",
1554 .features = &.{ "64bit", "a", "c", "d", "f", "i", "m" },
1555 },
1556 .{
1557 .llvm_name = null,
1558 .zig_name = "spacemit_a100",
1559 .features = &.{
1560 "64bit",
1561 "a",
1562 "b",
1563 "c",
1564 "dlen_factor_2",
1565 "i",
1566 "m",
1567 "optimized_nf2_segment_load_store",
1568 "optimized_nf3_segment_load_store",
1569 "optimized_nf4_segment_load_store",
1570 "smepmp",
1571 "smnpm",
1572 "smstateen",
1573 "ssccptr",
1574 "sscofpmf",
1575 "sscounterenw",
1576 "ssnpm",
1577 "sspm",
1578 "sstc",
1579 "sstvala",
1580 "sstvecd",
1581 "ssu64xl",
1582 "supm",
1583 "svade",
1584 "svbare",
1585 "svinval",
1586 "svnapot",
1587 "svpbmt",
1588 "unaligned_scalar_mem",
1589 "v",
1590 "vxrm_pipeline_flush",
1591 "za64rs",
1592 "zawrs",
1593 "zbc",
1594 "zbkc",
1595 "zcb",
1596 "zcmop",
1597 "zfa",
1598 "zfh",
1599 "zic64b",
1600 "zicbom",
1601 "zicbop",
1602 "zicboz",
1603 "ziccamoa",
1604 "ziccif",
1605 "zicclsm",
1606 "ziccrse",
1607 "zicntr",
1608 "zicond",
1609 "zifencei",
1610 "zihintntl",
1611 "zihintpause",
1612 "zihpm",
1613 "zimop",
1614 "zkt",
1615 "zvbb",
1616 "zvfbfwma",
1617 "zvfh",
1618 "zvkng",
1619 "zvknha",
1620 "zvksc",
1621 "zvksg",
1622 "zvl1024b",
1623 },
1624 },
1625 .{
1626 .llvm_name = null,
1627 .zig_name = "spacemit_x100",
1628 .features = &.{
1629 "dlen_factor_2",
1630 "optimized_nf2_segment_load_store",
1631 "optimized_nf3_segment_load_store",
1632 "optimized_nf4_segment_load_store",
1633 "rva23s64",
1634 "smepmp",
1635 "smnpm",
1636 "smstateen",
1637 "sspm",
1638 "unaligned_scalar_mem",
1639 "vxrm_pipeline_flush",
1640 "xsmtvdot",
1641 "zbc",
1642 "zbkc",
1643 "zfh",
1644 "zvfbfwma",
1645 "zvfh",
1646 "zvkng",
1647 "zvknha",
1648 "zvksc",
1649 "zvksg",
1650 "zvl256b",
1651 },
1652 },
1653 },
1654 },
1655 .{
1656 .zig_name = "sparc",
1657 .llvm = .{
1658 .name = "Sparc",
1659 .td_name = "Sparc",
1660 },
1661 },
1662 .{
1663 .zig_name = "s390x",
1664 .llvm = .{
1665 .name = "SystemZ",
1666 .td_name = "SystemZ",
1667 },
1668 },
1669 .{
1670 .zig_name = "ve",
1671 .llvm = .{
1672 .name = "VE",
1673 .td_name = "VE",
1674 },
1675 },
1676 .{
1677 .zig_name = "wasm",
1678 .llvm = .{
1679 .name = "WebAssembly",
1680 .td_name = "WebAssembly",
1681 },
1682 // For whatever reason, LLVM's WebAssembly backend sets these implied features in code
1683 // rather than making them proper dependencies, so fix that here...
1684 .feature_overrides = &.{
1685 .{
1686 .llvm_name = "bulk-memory",
1687 .extra_deps = &.{"bulk_memory_opt"},
1688 },
1689 .{
1690 .llvm_name = "reference-types",
1691 .extra_deps = &.{"call_indirect_overlong"},
1692 },
1693 },
1694 .extra_features = &.{
1695 .{
1696 .zig_name = "nontrapping_bulk_memory_len0",
1697 .desc = "Bulk memory operations with a zero length do not trap",
1698 .deps = &.{"bulk_memory_opt"},
1699 },
1700 },
1701 },
1702 .{
1703 .zig_name = "x86",
1704 .llvm = .{
1705 .name = "X86",
1706 .td_name = "X86",
1707 },
1708 .feature_overrides = &.{
1709 .{
1710 .llvm_name = "64bit-mode",
1711 .omit = true,
1712 },
1713 .{
1714 .llvm_name = "avx10.1-512",
1715 .omit = true,
1716 },
1717 .{
1718 .llvm_name = "avx10.2-512",
1719 .omit = true,
1720 },
1721 .{
1722 .llvm_name = "evex512",
1723 .omit = true,
1724 },
1725 .{
1726 .llvm_name = "alderlake",
1727 .extra_deps = &.{ "smap", "smep" },
1728 },
1729 .{
1730 .llvm_name = "amdfam10",
1731 .extra_deps = &.{"3dnowa"},
1732 },
1733 .{
1734 .llvm_name = "arrowlake",
1735 .extra_deps = &.{ "smap", "smep" },
1736 },
1737 .{
1738 .llvm_name = "arrowlake-s",
1739 .extra_deps = &.{ "smap", "smep" },
1740 },
1741 .{
1742 .llvm_name = "athlon",
1743 .extra_deps = &.{"3dnowa"},
1744 },
1745 .{
1746 .llvm_name = "athlon64",
1747 .extra_deps = &.{"3dnowa"},
1748 },
1749 .{
1750 .llvm_name = "athlon64-sse3",
1751 .extra_deps = &.{"3dnowa"},
1752 },
1753 .{
1754 .llvm_name = "athlon-4",
1755 .extra_deps = &.{"3dnowa"},
1756 },
1757 .{
1758 .llvm_name = "athlon-fx",
1759 .extra_deps = &.{"3dnowa"},
1760 },
1761 .{
1762 .llvm_name = "athlon-mp",
1763 .extra_deps = &.{"3dnowa"},
1764 },
1765 .{
1766 .llvm_name = "athlon-tbird",
1767 .extra_deps = &.{"3dnowa"},
1768 },
1769 .{
1770 .llvm_name = "athlon-xp",
1771 .extra_deps = &.{"3dnowa"},
1772 },
1773 .{
1774 .llvm_name = "barcelona",
1775 .extra_deps = &.{ "3dnowa", "smap", "smep" },
1776 },
1777 .{
1778 .llvm_name = "broadwell",
1779 .extra_deps = &.{ "smap", "smep" },
1780 },
1781 .{
1782 .llvm_name = "c3",
1783 .extra_deps = &.{"3dnow"},
1784 },
1785 .{
1786 .llvm_name = "cannonlake",
1787 .extra_deps = &.{ "smap", "smep" },
1788 },
1789 .{
1790 .llvm_name = "cascadelake",
1791 .extra_deps = &.{ "smap", "smep" },
1792 },
1793 .{
1794 .llvm_name = "emeraldrapids",
1795 .extra_deps = &.{ "smap", "smep" },
1796 },
1797 .{
1798 .llvm_name = "geode",
1799 .extra_deps = &.{"3dnowa"},
1800 },
1801 .{
1802 .llvm_name = "goldmont",
1803 .extra_deps = &.{ "smap", "smep" },
1804 },
1805 .{
1806 .llvm_name = "goldmont_plus",
1807 .extra_deps = &.{ "smap", "smep" },
1808 },
1809 .{
1810 .llvm_name = "haswell",
1811 .extra_deps = &.{"smep"},
1812 },
1813 .{
1814 .llvm_name = "i386",
1815 .extra_deps = &.{"bsf_bsr_0_clobbers_result"},
1816 },
1817 .{
1818 .llvm_name = "i486",
1819 .extra_deps = &.{"bsf_bsr_0_clobbers_result"},
1820 },
1821 .{
1822 .llvm_name = "icelake_client",
1823 .extra_deps = &.{ "smap", "smep" },
1824 },
1825 .{
1826 .llvm_name = "icelake_server",
1827 .extra_deps = &.{ "smap", "smep" },
1828 },
1829 .{
1830 .llvm_name = "ivybridge",
1831 .extra_deps = &.{"smep"},
1832 },
1833 .{
1834 .llvm_name = "k6-2",
1835 .extra_deps = &.{"3dnow"},
1836 },
1837 .{
1838 .llvm_name = "k6-3",
1839 .extra_deps = &.{"3dnow"},
1840 },
1841 .{
1842 .llvm_name = "k8",
1843 .extra_deps = &.{"3dnowa"},
1844 },
1845 .{
1846 .llvm_name = "k8-sse3",
1847 .extra_deps = &.{"3dnowa"},
1848 },
1849 .{
1850 .llvm_name = "knl",
1851 .extra_deps = &.{
1852 "avx512er",
1853 "avx512pf",
1854 "prefetchwt1",
1855 },
1856 },
1857 .{
1858 .llvm_name = "knm",
1859 .extra_deps = &.{
1860 "avx512er",
1861 "avx512pf",
1862 "prefetchwt1",
1863 },
1864 },
1865 .{
1866 .llvm_name = "lakemont",
1867 .extra_deps = &.{"soft_float"},
1868 },
1869 .{
1870 .llvm_name = "meteorlake",
1871 .extra_deps = &.{ "smap", "smep" },
1872 },
1873 .{
1874 .llvm_name = "opteron",
1875 .extra_deps = &.{"3dnowa"},
1876 },
1877 .{
1878 .llvm_name = "opteron-sse3",
1879 .extra_deps = &.{"3dnowa"},
1880 },
1881 .{
1882 .llvm_name = "raptorlake",
1883 .extra_deps = &.{ "smap", "smep" },
1884 },
1885 .{
1886 .llvm_name = "rocketlake",
1887 .extra_deps = &.{ "smap", "smep" },
1888 },
1889 .{
1890 .llvm_name = "sapphirerapids",
1891 .extra_deps = &.{ "smap", "smep" },
1892 },
1893 .{
1894 .llvm_name = "silvermont",
1895 .extra_deps = &.{"smep"},
1896 },
1897 .{
1898 .llvm_name = "skx",
1899 .extra_deps = &.{ "smap", "smep" },
1900 },
1901 .{
1902 .llvm_name = "skylake",
1903 .extra_deps = &.{ "smap", "smep" },
1904 },
1905 .{
1906 .llvm_name = "skylake_avx512",
1907 .extra_deps = &.{ "smap", "smep" },
1908 },
1909 .{
1910 .llvm_name = "tigerlake",
1911 .extra_deps = &.{ "smap", "smep" },
1912 },
1913 .{
1914 .llvm_name = "winchip2",
1915 .extra_deps = &.{"3dnow"},
1916 },
1917 .{
1918 .llvm_name = "sse4.2",
1919 .extra_deps = &.{"crc32"},
1920 },
1921 .{
1922 .llvm_name = "znver1",
1923 .extra_deps = &.{ "smap", "smep" },
1924 },
1925 .{
1926 .llvm_name = "znver2",
1927 .extra_deps = &.{ "smap", "smep" },
1928 },
1929 .{
1930 .llvm_name = "znver3",
1931 .extra_deps = &.{ "smap", "smep" },
1932 },
1933 .{
1934 .llvm_name = "znver4",
1935 .extra_deps = &.{ "smap", "smep" },
1936 },
1937 .{
1938 .llvm_name = "znver5",
1939 .extra_deps = &.{ "smap", "smep" },
1940 },
1941 },
1942 .extra_features = &.{
1943 // Features removed from LLVM
1944 .{
1945 .zig_name = "3dnow",
1946 .desc = "Enable 3DNow! instructions",
1947 .deps = &.{"mmx"},
1948 },
1949 .{
1950 .zig_name = "3dnowa",
1951 .desc = "Enable 3DNow! Athlon instructions",
1952 .deps = &.{"3dnow"},
1953 },
1954 .{
1955 .zig_name = "avx512er",
1956 .desc = "Enable AVX-512 Exponential and Reciprocal Instructions",
1957 .deps = &.{"avx512f"},
1958 },
1959 .{
1960 .zig_name = "avx512pf",
1961 .desc = "Enable AVX-512 PreFetch Instructions",
1962 .deps = &.{"avx512f"},
1963 },
1964 .{
1965 .zig_name = "prefetchwt1",
1966 .desc = "Prefetch with Intent to Write and T1 Hint",
1967 .deps = &.{},
1968 },
1969 // Custom Zig features
1970 .{
1971 .zig_name = "bsf_bsr_0_clobbers_result",
1972 .desc = "BSF/BSR may clobber the lower 32-bits of the result register when the source is zero",
1973 .deps = &.{},
1974 },
1975 .{
1976 .zig_name = "smap",
1977 .desc = "Enable Supervisor Mode Access Prevention",
1978 .deps = &.{},
1979 },
1980 .{
1981 .zig_name = "smep",
1982 .desc = "Enable Supervisor Mode Execution Prevention",
1983 .deps = &.{},
1984 },
1985 },
1986 .extra_cpus = &.{
1987 .{
1988 .llvm_name = null,
1989 .zig_name = "i86",
1990 .features = &.{"16bit_mode"},
1991 },
1992 },
1993 .omit_cpus = &.{
1994 // LLVM defines a bunch of dumb aliases with foreach loops in X86.td.
1995 "pentium_mmx",
1996 "pentium_pro",
1997 "pentium_ii",
1998 "pentium_3m",
1999 "pentium_iii_no_xmm_regs",
2000 "pentium_iii",
2001 "pentium_m",
2002 "pentium4m",
2003 "pentium_4",
2004 "pentium_4_sse3",
2005 "core_2_duo_ssse3",
2006 "core_2_duo_sse4_1",
2007 "atom_sse4_2",
2008 "goldmont_plus",
2009 "core_i7_sse4_2",
2010 "core_aes_pclmulqdq",
2011 "corei7-avx",
2012 "core_2nd_gen_avx",
2013 "core-avx-i",
2014 "core_3rd_gen_avx",
2015 "core-avx2",
2016 "core_4th_gen_avx",
2017 "core_4th_gen_avx_tsx",
2018 "core_5th_gen_avx",
2019 "core_5th_gen_avx_tsx",
2020 "mic_avx512",
2021 "skylake_avx512",
2022 "icelake_client",
2023 "icelake_server",
2024 "graniterapids_d",
2025 "arrowlake_s",
2026 },
2027 },
2028 .{
2029 .zig_name = "xcore",
2030 .llvm = .{
2031 .name = "XCore",
2032 .td_name = "XCore",
2033 },
2034 },
2035 .{
2036 .zig_name = "xtensa",
2037 .llvm = .{
2038 .name = "Xtensa",
2039 .td_name = "Xtensa",
2040 },
2041 },
2042};
2043
2044pub fn main(init: std.process.Init) !void {
2045 const arena = init.arena.allocator();
2046 const io = init.io;
2047
2048 var args = try init.minimal.args.iterateAllocator(arena);
2049 const args0 = args.next().?;
2050
2051 const llvm_tblgen_exe = args.next() orelse
2052 usageAndExit(args0, 1);
2053
2054 if (std.mem.eql(u8, llvm_tblgen_exe, "--help")) {
2055 usageAndExit(args0, 0);
2056 }
2057 if (std.mem.startsWith(u8, llvm_tblgen_exe, "-")) {
2058 usageAndExit(args0, 1);
2059 }
2060
2061 const llvm_src_root = args.next() orelse
2062 usageAndExit(args0, 1);
2063
2064 if (std.mem.startsWith(u8, llvm_src_root, "-")) {
2065 usageAndExit(args0, 1);
2066 }
2067
2068 const zig_src_root = args.next() orelse
2069 usageAndExit(args0, 1);
2070
2071 if (std.mem.startsWith(u8, zig_src_root, "-")) {
2072 usageAndExit(args0, 1);
2073 }
2074
2075 var filter: ?[]const u8 = null;
2076 if (args.next()) |arg| filter = arg;
2077
2078 // there shouldn't be any more argument after the optional filter
2079 if (args.skip()) usageAndExit(args0, 1);
2080
2081 var zig_src_dir = try Dir.cwd().openDir(io, zig_src_root, .{});
2082 defer zig_src_dir.close(io);
2083
2084 const root_progress = std.Progress.start(io, .{ .estimated_total_items = targets.len });
2085 defer root_progress.end();
2086
2087 var group: Io.Group = .init;
2088 defer group.cancel(io);
2089
2090 for (targets) |target| {
2091 if (filter) |zig_name| {
2092 if (!std.mem.eql(u8, target.zig_name, zig_name)) continue;
2093 }
2094 group.async(io, processOneTarget, .{ io, .{
2095 .llvm_tblgen_exe = llvm_tblgen_exe,
2096 .llvm_src_root = llvm_src_root,
2097 .zig_src_dir = zig_src_dir,
2098 .root_progress = root_progress,
2099 .target = target,
2100 } });
2101 }
2102
2103 try group.await(io);
2104}
2105
2106const Job = struct {
2107 llvm_tblgen_exe: []const u8,
2108 llvm_src_root: []const u8,
2109 zig_src_dir: Dir,
2110 root_progress: std.Progress.Node,
2111 target: ArchTarget,
2112};
2113
2114fn processOneTarget(io: Io, job: Job) void {
2115 processOneTargetInner(io, job) catch |err| std.debug.panic("panic: {s}", .{@errorName(err)});
2116}
2117fn processOneTargetInner(io: Io, job: Job) !void {
2118 const target = job.target;
2119
2120 var arena_state = std.heap.ArenaAllocator.init(std.heap.page_allocator);
2121 defer arena_state.deinit();
2122 const arena = arena_state.allocator();
2123
2124 const progress_node = job.root_progress.start(target.zig_name, 3);
2125 defer progress_node.end();
2126
2127 var features_table = std.StringHashMap(Feature).init(arena);
2128 var all_features = std.array_list.Managed(Feature).init(arena);
2129 var all_cpus = std.array_list.Managed(Cpu).init(arena);
2130
2131 if (target.llvm) |llvm| {
2132 const tblgen_progress = progress_node.start("running llvm-tblgen", 0);
2133
2134 const child_args = [_][]const u8{
2135 job.llvm_tblgen_exe,
2136 "--dump-json",
2137 try std.fmt.allocPrint(arena, "{s}/llvm/lib/Target/{s}/{s}.td", .{
2138 job.llvm_src_root,
2139 llvm.name,
2140 llvm.td_name,
2141 }),
2142 try std.fmt.allocPrint(arena, "-I={s}/llvm/include", .{job.llvm_src_root}),
2143 try std.fmt.allocPrint(arena, "-I={s}/llvm/lib/Target/{s}", .{
2144 job.llvm_src_root, llvm.name,
2145 }),
2146 };
2147
2148 const child_result = try std.process.run(arena, io, .{
2149 .argv = &child_args,
2150 });
2151 tblgen_progress.end();
2152 if (child_result.stderr.len != 0) {
2153 std.debug.print("{s}\n", .{child_result.stderr});
2154 }
2155
2156 const json_text = switch (child_result.term) {
2157 .exited => |code| if (code == 0) child_result.stdout else {
2158 std.debug.print("llvm-tblgen exited with code {d}\n", .{code});
2159 std.process.exit(1);
2160 },
2161 .signal => |sig| {
2162 std.debug.print("llvm-tblgen terminated with signal {t}\n", .{sig});
2163 std.process.exit(1);
2164 },
2165 .stopped => |sig| {
2166 std.debug.print("llvm-tblgen stopped with signal {t}\n", .{sig});
2167 std.process.exit(1);
2168 },
2169 .unknown => {
2170 std.debug.print("llvm-tblgen crashed\n", .{});
2171 std.process.exit(1);
2172 },
2173 };
2174
2175 const json_parse_progress = progress_node.start("parsing JSON", 0);
2176
2177 const parsed = try json.parseFromSlice(json.Value, arena, json_text, .{});
2178 defer parsed.deinit();
2179 const root_map = &parsed.value.object;
2180 json_parse_progress.end();
2181
2182 const collate_progress = progress_node.start("collating LLVM data", 0);
2183
2184 // So far, LLVM only has a few aliases for the same CPU.
2185 const Alias = struct {
2186 llvm: []const u8,
2187 zig: []const u8,
2188 };
2189 var cpu_aliases = std.StringHashMap(std.ArrayList(*Alias)).init(arena);
2190
2191 {
2192 var it = root_map.iterator();
2193 while (it.next()) |kv| {
2194 if (kv.key_ptr.len == 0) continue;
2195 if (kv.key_ptr.*[0] == '!') continue;
2196 if (kv.value_ptr.* != .object) continue;
2197 if (hasSuperclass(&kv.value_ptr.object, "ProcessorAlias")) {
2198 // Note that `Name` is actually the alias, while `Alias` is the name that will have
2199 // a full `Processor` object defined.
2200 const llvm_alias = kv.value_ptr.object.get("Name").?.string;
2201 const llvm_name = kv.value_ptr.object.get("Alias").?.string;
2202
2203 const gop = try cpu_aliases.getOrPut(try llvmNameToZigName(arena, llvm_name));
2204
2205 if (!gop.found_existing) {
2206 gop.value_ptr.* = .empty;
2207 }
2208
2209 const alias = try arena.create(Alias);
2210 alias.* = .{
2211 .llvm = llvm_alias,
2212 .zig = try llvmNameToZigName(arena, llvm_alias),
2213 };
2214 try gop.value_ptr.append(arena, alias);
2215 }
2216 }
2217 }
2218
2219 {
2220 var it = root_map.iterator();
2221 while (it.next()) |kv| {
2222 if (kv.key_ptr.len == 0) continue;
2223 if (kv.key_ptr.*[0] == '!') continue;
2224 if (kv.value_ptr.* != .object) continue;
2225 if (hasSuperclass(&kv.value_ptr.object, "SubtargetFeature")) {
2226 const llvm_name = kv.value_ptr.object.get("Name").?.string;
2227 if (llvm_name.len == 0) continue;
2228
2229 var zig_name = try llvmNameToZigName(arena, llvm_name);
2230 var desc = kv.value_ptr.object.get("Desc").?.string;
2231 var deps = std.array_list.Managed([]const u8).init(arena);
2232 var omit = false;
2233 var flatten = false;
2234 var omit_deps: []const []const u8 = &.{};
2235 var extra_deps: []const []const u8 = &.{};
2236 for (target.feature_overrides) |feature_override| {
2237 if (mem.eql(u8, llvm_name, feature_override.llvm_name)) {
2238 if (feature_override.omit) {
2239 // Still put the feature into the table so that we can
2240 // expand dependencies for the feature overrides marked `flatten`.
2241 omit = true;
2242 }
2243 if (feature_override.flatten) {
2244 flatten = true;
2245 }
2246 if (feature_override.zig_name) |override_name| {
2247 zig_name = override_name;
2248 }
2249 if (feature_override.desc) |override_desc| {
2250 desc = override_desc;
2251 }
2252 omit_deps = feature_override.omit_deps;
2253 extra_deps = feature_override.extra_deps;
2254 break;
2255 }
2256 }
2257 const implies = kv.value_ptr.object.get("Implies").?.array;
2258 for (implies.items) |imply| {
2259 const other_key = imply.object.get("def").?.string;
2260 const other_obj = root_map.get(other_key).?.object;
2261 const other_llvm_name = other_obj.get("Name").?.string;
2262 const other_zig_name = (try llvmFeatureNameToZigNameOmit(
2263 arena,
2264 target,
2265 other_llvm_name,
2266 )) orelse continue;
2267 for (omit_deps) |omit_dep| {
2268 if (mem.eql(u8, other_zig_name, omit_dep)) break;
2269 } else {
2270 try deps.append(other_zig_name);
2271 }
2272 }
2273 // This is used by AArch64.
2274 if (kv.value_ptr.object.get("DefaultExts")) |exts_val| {
2275 for (exts_val.array.items) |ext| {
2276 const other_key = ext.object.get("def").?.string;
2277 const other_obj = root_map.get(other_key).?.object;
2278 const other_llvm_name = other_obj.get("Name").?.string;
2279 const other_zig_name = (try llvmFeatureNameToZigNameOmit(
2280 arena,
2281 target,
2282 other_llvm_name,
2283 )) orelse continue;
2284 for (omit_deps) |omit_dep| {
2285 if (mem.eql(u8, other_zig_name, omit_dep)) break;
2286 } else {
2287 try deps.append(other_zig_name);
2288 }
2289 }
2290 }
2291 for (extra_deps) |extra_dep| {
2292 try deps.append(extra_dep);
2293 }
2294 const feature: Feature = .{
2295 .llvm_name = llvm_name,
2296 .zig_name = zig_name,
2297 .desc = desc,
2298 .deps = deps.items,
2299 .flatten = flatten,
2300 };
2301 try features_table.put(zig_name, feature);
2302 if (!omit and !flatten) {
2303 try all_features.append(feature);
2304 }
2305 }
2306 if (hasSuperclass(&kv.value_ptr.object, "Processor")) {
2307 const llvm_name = kv.value_ptr.object.get("Name").?.string;
2308 if (llvm_name.len == 0) continue;
2309 const omitted = for (target.omit_cpus) |omit_cpu_name| {
2310 if (mem.eql(u8, omit_cpu_name, llvm_name)) break true;
2311 } else false;
2312 if (omitted) continue;
2313
2314 var zig_name = try llvmNameToZigName(arena, llvm_name);
2315 var deps = std.array_list.Managed([]const u8).init(arena);
2316 var omit_deps: []const []const u8 = &.{};
2317 var extra_deps: []const []const u8 = &.{};
2318 for (target.feature_overrides) |feature_override| {
2319 if (mem.eql(u8, llvm_name, feature_override.llvm_name)) {
2320 if (feature_override.omit) {
2321 continue;
2322 }
2323 if (feature_override.zig_name) |override_name| {
2324 zig_name = override_name;
2325 }
2326 omit_deps = feature_override.omit_deps;
2327 extra_deps = feature_override.extra_deps;
2328 break;
2329 }
2330 }
2331 const features = kv.value_ptr.object.get("Features").?.array;
2332 for (features.items) |feature| {
2333 const feature_key = feature.object.get("def").?.string;
2334 const feature_obj = root_map.get(feature_key).?.object;
2335 const feature_llvm_name = feature_obj.get("Name").?.string;
2336 if (feature_llvm_name.len == 0) continue;
2337 const feature_zig_name = (try llvmFeatureNameToZigNameOmit(
2338 arena,
2339 target,
2340 feature_llvm_name,
2341 )) orelse continue;
2342 for (omit_deps) |omit_dep| {
2343 if (mem.eql(u8, feature_zig_name, omit_dep)) break;
2344 } else {
2345 try deps.append(feature_zig_name);
2346 }
2347 }
2348 for (extra_deps) |extra_dep| {
2349 try deps.append(extra_dep);
2350 }
2351 const tune_features = kv.value_ptr.object.get("TuneFeatures").?.array;
2352 for (tune_features.items) |feature| {
2353 const feature_key = feature.object.get("def").?.string;
2354 const feature_obj = root_map.get(feature_key).?.object;
2355 const feature_llvm_name = feature_obj.get("Name").?.string;
2356 if (feature_llvm_name.len == 0) continue;
2357 const feature_zig_name = (try llvmFeatureNameToZigNameOmit(
2358 arena,
2359 target,
2360 feature_llvm_name,
2361 )) orelse continue;
2362 try deps.append(feature_zig_name);
2363 }
2364 try all_cpus.append(.{
2365 .llvm_name = llvm_name,
2366 .zig_name = zig_name,
2367 .features = deps.items,
2368 });
2369
2370 if (cpu_aliases.get(zig_name)) |aliases| {
2371 alias_it: for (aliases.items) |alias| {
2372 for (target.omit_cpus) |omit_cpu_name| {
2373 if (mem.eql(u8, omit_cpu_name, alias.llvm)) continue :alias_it;
2374 }
2375
2376 try all_cpus.append(.{
2377 .llvm_name = alias.llvm,
2378 .zig_name = alias.zig,
2379 .features = deps.items,
2380 });
2381 }
2382 }
2383 }
2384 }
2385 }
2386
2387 collate_progress.end();
2388 }
2389
2390 for (target.extra_features) |extra_feature| {
2391 try features_table.put(extra_feature.zig_name, extra_feature);
2392 try all_features.append(extra_feature);
2393 }
2394 for (target.extra_cpus) |extra_cpu| {
2395 try all_cpus.append(extra_cpu);
2396 }
2397 mem.sort(Feature, all_features.items, {}, featureLessThan);
2398 mem.sort(Cpu, all_cpus.items, {}, cpuLessThan);
2399
2400 const render_progress = progress_node.start("rendering Zig code", 0);
2401
2402 var target_dir = try job.zig_src_dir.openDir(io, "lib/std/Target", .{});
2403 defer target_dir.close(io);
2404
2405 const zig_code_basename = try std.fmt.allocPrint(arena, "{s}.zig", .{target.zig_name});
2406 var zig_code_file = try target_dir.createFile(io, zig_code_basename, .{});
2407 defer zig_code_file.close(io);
2408
2409 var zig_code_file_buffer: [4096]u8 = undefined;
2410 var zig_code_file_writer = zig_code_file.writer(io, &zig_code_file_buffer);
2411 const w = &zig_code_file_writer.interface;
2412
2413 try w.writeAll(
2414 \\//! This file is auto-generated by tools/update_cpu_features.zig.
2415 \\
2416 \\const std = @import("../std.zig");
2417 \\const CpuFeature = std.Target.Cpu.Feature;
2418 \\const CpuModel = std.Target.Cpu.Model;
2419 \\
2420 \\pub const Feature = enum {
2421 );
2422
2423 for (all_features.items, 0..) |feature, i| {
2424 try w.print("\n {f},", .{std.zig.fmtIdPU(feature.zig_name)});
2425
2426 if (i == all_features.items.len - 1) try w.writeAll("\n");
2427 }
2428
2429 try w.writeAll(
2430 \\};
2431 \\
2432 \\pub const featureSet = CpuFeature.FeatureSetFns(Feature).featureSet;
2433 \\pub const featureSetHas = CpuFeature.FeatureSetFns(Feature).featureSetHas;
2434 \\pub const featureSetHasAny = CpuFeature.FeatureSetFns(Feature).featureSetHasAny;
2435 \\pub const featureSetHasAll = CpuFeature.FeatureSetFns(Feature).featureSetHasAll;
2436 \\
2437 \\pub const all_features = blk: {
2438 \\
2439 );
2440 if (target.branch_quota) |branch_quota| {
2441 try w.print(" @setEvalBranchQuota({d});\n", .{branch_quota});
2442 }
2443 try w.writeAll(
2444 \\ const len = @typeInfo(Feature).@"enum".field_names.len;
2445 \\ std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
2446 \\ var result: [len]CpuFeature = undefined;
2447 \\
2448 );
2449
2450 for (all_features.items) |feature| {
2451 if (feature.llvm_name) |llvm_name| {
2452 try w.print(
2453 \\ result[@intFromEnum(Feature.{f})] = .{{
2454 \\ .llvm_name = "{f}",
2455 \\ .description = "{f}",
2456 \\ .dependencies = featureSet(&[_]Feature{{
2457 ,
2458 .{
2459 std.zig.fmtIdPU(feature.zig_name),
2460 std.zig.fmtString(llvm_name),
2461 std.zig.fmtString(feature.desc),
2462 },
2463 );
2464 } else {
2465 try w.print(
2466 \\ result[@intFromEnum(Feature.{f})] = .{{
2467 \\ .llvm_name = null,
2468 \\ .description = "{f}",
2469 \\ .dependencies = featureSet(&[_]Feature{{
2470 ,
2471 .{
2472 std.zig.fmtIdPU(feature.zig_name),
2473 std.zig.fmtString(feature.desc),
2474 },
2475 );
2476 }
2477 var deps_set = std.StringHashMap(void).init(arena);
2478 for (feature.deps) |dep| {
2479 try putDep(&deps_set, features_table, dep);
2480 }
2481 try pruneFeatures(arena, features_table, &deps_set);
2482 var dependencies = std.array_list.Managed([]const u8).init(arena);
2483 {
2484 var it = deps_set.keyIterator();
2485 while (it.next()) |key| {
2486 try dependencies.append(key.*);
2487 }
2488 }
2489 mem.sort([]const u8, dependencies.items, {}, asciiLessThan);
2490
2491 if (dependencies.items.len == 0) {
2492 try w.writeAll(
2493 \\}),
2494 \\ };
2495 \\
2496 );
2497 } else {
2498 try w.writeAll("\n");
2499 for (dependencies.items) |dep| {
2500 try w.print(" .{f},\n", .{std.zig.fmtIdPU(dep)});
2501 }
2502 try w.writeAll(
2503 \\ }),
2504 \\ };
2505 \\
2506 );
2507 }
2508 }
2509 try w.writeAll(
2510 \\ const ti = @typeInfo(Feature);
2511 \\ for (&result, 0..) |*elem, i| {
2512 \\ elem.index = i;
2513 \\ elem.name = ti.@"enum".field_names[i];
2514 \\ }
2515 \\ break :blk result;
2516 \\};
2517 \\
2518 \\pub const cpu = struct {
2519 \\
2520 );
2521 for (all_cpus.items) |cpu| {
2522 var deps_set = std.StringHashMap(void).init(arena);
2523 for (cpu.features) |feature_zig_name| {
2524 try putDep(&deps_set, features_table, feature_zig_name);
2525 }
2526 try pruneFeatures(arena, features_table, &deps_set);
2527 var cpu_features = std.array_list.Managed([]const u8).init(arena);
2528 {
2529 var it = deps_set.keyIterator();
2530 while (it.next()) |key| {
2531 try cpu_features.append(key.*);
2532 }
2533 }
2534 mem.sort([]const u8, cpu_features.items, {}, asciiLessThan);
2535 if (cpu.llvm_name) |llvm_name| {
2536 try w.print(
2537 \\ pub const {f}: CpuModel = .{{
2538 \\ .name = "{f}",
2539 \\ .llvm_name = "{f}",
2540 \\ .features = featureSet(&[_]Feature{{
2541 , .{
2542 std.zig.fmtId(cpu.zig_name),
2543 std.zig.fmtString(cpu.zig_name),
2544 std.zig.fmtString(llvm_name),
2545 });
2546 } else {
2547 try w.print(
2548 \\ pub const {f}: CpuModel = .{{
2549 \\ .name = "{f}",
2550 \\ .llvm_name = null,
2551 \\ .features = featureSet(&[_]Feature{{
2552 , .{
2553 std.zig.fmtId(cpu.zig_name),
2554 std.zig.fmtString(cpu.zig_name),
2555 });
2556 }
2557 if (cpu_features.items.len == 0) {
2558 try w.writeAll(
2559 \\}),
2560 \\ };
2561 \\
2562 );
2563 } else {
2564 try w.writeAll("\n");
2565 for (cpu_features.items) |feature_zig_name| {
2566 try w.print(" .{f},\n", .{std.zig.fmtIdPU(feature_zig_name)});
2567 }
2568 try w.writeAll(
2569 \\ }),
2570 \\ };
2571 \\
2572 );
2573 }
2574 }
2575
2576 try w.writeAll(
2577 \\};
2578 \\
2579 );
2580 try w.flush();
2581
2582 render_progress.end();
2583}
2584
2585fn usageAndExit(arg0: []const u8, code: u8) noreturn {
2586 const stderr = std.debug.lockStderr(&.{});
2587 const w = &stderr.file_writer.interface;
2588 w.print(
2589 \\Usage: {s} /path/to/llvm-tblgen /path/git/llvm-project /path/git/zig [zig_name filter]
2590 \\
2591 \\Updates lib/std/target/<target>.zig from llvm/lib/Target/<Target>/<Target>.td .
2592 \\
2593 \\On a less beefy system, or when debugging, compile with -fsingle-threaded.
2594 \\
2595 , .{arg0}) catch std.process.exit(1);
2596 std.process.exit(code);
2597}
2598
2599fn featureLessThan(_: void, a: Feature, b: Feature) bool {
2600 return std.ascii.lessThanIgnoreCase(a.zig_name, b.zig_name);
2601}
2602
2603fn cpuLessThan(_: void, a: Cpu, b: Cpu) bool {
2604 return std.ascii.lessThanIgnoreCase(a.zig_name, b.zig_name);
2605}
2606
2607fn asciiLessThan(_: void, a: []const u8, b: []const u8) bool {
2608 return std.ascii.lessThanIgnoreCase(a, b);
2609}
2610
2611fn llvmNameToZigName(arena: mem.Allocator, llvm_name: []const u8) ![]const u8 {
2612 const duped = try arena.dupe(u8, llvm_name);
2613 for (duped) |*byte| switch (byte.*) {
2614 '-', '.' => byte.* = '_',
2615 else => continue,
2616 };
2617 return duped;
2618}
2619
2620fn llvmFeatureNameToZigNameOmit(
2621 arena: mem.Allocator,
2622 target: ArchTarget,
2623 llvm_name: []const u8,
2624) !?[]const u8 {
2625 for (target.feature_overrides) |feature_override| {
2626 if (mem.eql(u8, feature_override.llvm_name, llvm_name)) {
2627 if (feature_override.omit) return null;
2628 return feature_override.zig_name orelse break;
2629 }
2630 }
2631 return try llvmNameToZigName(arena, llvm_name);
2632}
2633
2634fn hasSuperclass(obj: *const json.ObjectMap, class_name: []const u8) bool {
2635 const superclasses_json = obj.get("!superclasses") orelse return false;
2636 for (superclasses_json.array.items) |superclass_json| {
2637 const superclass = superclass_json.string;
2638 if (std.mem.eql(u8, superclass, class_name)) {
2639 return true;
2640 }
2641 }
2642 return false;
2643}
2644
2645fn pruneFeatures(
2646 arena: mem.Allocator,
2647 features_table: std.StringHashMap(Feature),
2648 deps_set: *std.StringHashMap(void),
2649) !void {
2650 // For each element, recursively iterate over the dependencies and add
2651 // everything we find to a "deletion set".
2652 // Then, iterate over the deletion set and delete all that stuff from `deps_set`.
2653 var deletion_set = std.StringHashMap(void).init(arena);
2654 {
2655 var it = deps_set.keyIterator();
2656 while (it.next()) |key| {
2657 const feature = features_table.get(key.*).?;
2658 try walkFeatures(features_table, &deletion_set, feature);
2659 }
2660 }
2661 {
2662 var it = deletion_set.keyIterator();
2663 while (it.next()) |key| {
2664 _ = deps_set.remove(key.*);
2665 }
2666 }
2667}
2668
2669fn walkFeatures(
2670 features_table: std.StringHashMap(Feature),
2671 deletion_set: *std.StringHashMap(void),
2672 feature: Feature,
2673) error{OutOfMemory}!void {
2674 for (feature.deps) |dep| {
2675 try deletion_set.put(dep, {});
2676 const other_feature = features_table.get(dep).?;
2677 try walkFeatures(features_table, deletion_set, other_feature);
2678 }
2679}
2680
2681fn putDep(
2682 deps_set: *std.StringHashMap(void),
2683 features_table: std.StringHashMap(Feature),
2684 zig_feature_name: []const u8,
2685) error{OutOfMemory}!void {
2686 const feature = features_table.get(zig_feature_name).?;
2687 if (feature.flatten) {
2688 for (feature.deps) |dep| {
2689 try putDep(deps_set, features_table, dep);
2690 }
2691 } else {
2692 try deps_set.put(zig_feature_name, {});
2693 }
2694}