authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-05-18 19:05:56+02:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-05-19 13:15:44+02:00
log0843d3e5f2092d1058c59d98b42d4119ac441817
tree252c65f69536b3424fb9e93f6feca64387e374c2
parent30698b03c0420e897244441a60a8a8d1a4ade9f4

compiler: delete llvm-ints and detect-cpu subcommands

* The llvm-ints subcommand hasn't been useful for a while since we're just using hardcoded data layout strings based on the target, rather than the old approach of building them up piecemeal. We additionally have the tools/generate_c_size_and_align_checks.zig script for catching C ABI mismatches. So this libLLVM dependency is not justified anymore. * The detect-cpu subcommand was at least somewhat useful to compare CPU detection results between Zig and LLVM. However, its usefulness hinged on running it natively on every relevant CPU, which we were not actually doing anyway. Besides, I make a point of porting CPU detection changes in LLVM to our CPU detection code on every LLVM upgrade - and in some cases, we even do it more correctly than LLVM now. So the libLLVM dependency brought by this subcommand also isn't really justified anymore.

1 files changed, 0 insertions(+), 182 deletions(-)

src/main.zig-182
......@@ -125,8 +125,6 @@ const debug_usage = normal_usage ++
125125 \\
126126 \\ changelist Compute mappings from old ZIR to new ZIR
127127 \\ dump-zir Dump a file containing cached ZIR
128 \\ detect-cpu Compare Zig's CPU feature detection vs LLVM
129 \\ llvm-ints Dump a list of LLVMABIAlignmentOfType for all integers
130128 \\
131129;
132130
......@@ -403,14 +401,10 @@ fn mainArgs(
403401 return Io.File.stdout().writeStreamingAll(io, usage);
404402 } else if (mem.eql(u8, cmd, "ast-check")) {
405403 return cmdAstCheck(arena, io, cmd_args);
406 } else if (mem.eql(u8, cmd, "detect-cpu")) {
407 return cmdDetectCpu(io, cmd_args);
408404 } else if (build_options.enable_debug_extensions and mem.eql(u8, cmd, "changelist")) {
409405 return cmdChangelist(arena, io, cmd_args);
410406 } else if (build_options.enable_debug_extensions and mem.eql(u8, cmd, "dump-zir")) {
411407 return cmdDumpZir(arena, io, cmd_args);
412 } else if (build_options.enable_debug_extensions and mem.eql(u8, cmd, "llvm-ints")) {
413 return cmdDumpLlvmInts(gpa, arena, io, cmd_args);
414408 } else {
415409 std.log.info("{s}", .{usage});
416410 fatal("unknown command: {s}", .{args[1]});
......@@ -6453,182 +6447,6 @@ fn cmdAstCheck(arena: Allocator, io: Io, args: []const []const u8) !void {
64536447 }
64546448}
64556449
6456fn cmdDetectCpu(io: Io, args: []const []const u8) !void {
6457 dev.check(.detect_cpu_command);
6458
6459 const detect_cpu_usage =
6460 \\Usage: zig detect-cpu [--llvm]
6461 \\
6462 \\ Print the host CPU name and feature set to stdout.
6463 \\
6464 \\Options:
6465 \\ -h, --help Print this help and exit
6466 \\ --llvm Detect using LLVM API
6467 \\
6468 ;
6469
6470 var use_llvm = false;
6471
6472 {
6473 var i: usize = 0;
6474 while (i < args.len) : (i += 1) {
6475 const arg = args[i];
6476 if (mem.startsWith(u8, arg, "-")) {
6477 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {
6478 try Io.File.stdout().writeStreamingAll(io, detect_cpu_usage);
6479 return cleanExit(io);
6480 } else if (mem.eql(u8, arg, "--llvm")) {
6481 use_llvm = true;
6482 } else {
6483 fatal("unrecognized parameter: '{s}'", .{arg});
6484 }
6485 } else {
6486 fatal("unexpected extra parameter: '{s}'", .{arg});
6487 }
6488 }
6489 }
6490
6491 if (use_llvm) {
6492 if (!build_options.have_llvm)
6493 fatal("compiler does not use LLVM; cannot compare CPU features with LLVM", .{});
6494
6495 const llvm = @import("codegen/llvm/bindings.zig");
6496 const name = llvm.GetHostCPUName() orelse fatal("LLVM could not figure out the host cpu name", .{});
6497 const features = llvm.GetHostCPUFeatures() orelse fatal("LLVM could not figure out the host cpu feature set", .{});
6498 const cpu = try detectNativeCpuWithLLVM(builtin.cpu.arch, name, features);
6499 try printCpu(io, cpu);
6500 } else {
6501 const host_target = std.zig.resolveTargetQueryOrFatal(io, .{});
6502 try printCpu(io, host_target.cpu);
6503 }
6504}
6505
6506fn detectNativeCpuWithLLVM(
6507 arch: std.Target.Cpu.Arch,
6508 llvm_cpu_name_z: ?[*:0]const u8,
6509 llvm_cpu_features_opt: ?[*:0]const u8,
6510) !std.Target.Cpu {
6511 var result = std.Target.Cpu.baseline(arch, builtin.os);
6512
6513 if (llvm_cpu_name_z) |cpu_name_z| {
6514 const llvm_cpu_name = mem.span(cpu_name_z);
6515
6516 for (arch.allCpuModels()) |model| {
6517 const this_llvm_name = model.llvm_name orelse continue;
6518 if (mem.eql(u8, this_llvm_name, llvm_cpu_name)) {
6519 // Here we use the non-dependencies-populated set,
6520 // so that subtracting features later in this function
6521 // affect the prepopulated set.
6522 result = std.Target.Cpu{
6523 .arch = arch,
6524 .model = model,
6525 .features = model.features,
6526 };
6527 break;
6528 }
6529 }
6530 }
6531
6532 const all_features = arch.allFeaturesList();
6533
6534 if (llvm_cpu_features_opt) |llvm_cpu_features| {
6535 var it = mem.tokenizeScalar(u8, mem.span(llvm_cpu_features), ',');
6536 while (it.next()) |decorated_llvm_feat| {
6537 var op: enum {
6538 add,
6539 sub,
6540 } = undefined;
6541 var llvm_feat: []const u8 = undefined;
6542 if (mem.startsWith(u8, decorated_llvm_feat, "+")) {
6543 op = .add;
6544 llvm_feat = decorated_llvm_feat[1..];
6545 } else if (mem.startsWith(u8, decorated_llvm_feat, "-")) {
6546 op = .sub;
6547 llvm_feat = decorated_llvm_feat[1..];
6548 } else {
6549 return error.InvalidLlvmCpuFeaturesFormat;
6550 }
6551 for (all_features, 0..) |feature, index_usize| {
6552 const this_llvm_name = feature.llvm_name orelse continue;
6553 if (mem.eql(u8, llvm_feat, this_llvm_name)) {
6554 const index: std.Target.Cpu.Feature.Set.Index = @intCast(index_usize);
6555 switch (op) {
6556 .add => result.features.addFeature(index),
6557 .sub => result.features.removeFeature(index),
6558 }
6559 break;
6560 }
6561 }
6562 }
6563 }
6564
6565 result.features.populateDependencies(all_features);
6566 return result;
6567}
6568
6569fn printCpu(io: Io, cpu: std.Target.Cpu) !void {
6570 var stdout_writer = Io.File.stdout().writerStreaming(io, &stdout_buffer);
6571 const stdout_bw = &stdout_writer.interface;
6572
6573 if (cpu.model.llvm_name) |llvm_name| {
6574 try stdout_bw.print("{s}\n", .{llvm_name});
6575 }
6576
6577 const all_features = cpu.arch.allFeaturesList();
6578 for (all_features, 0..) |feature, index_usize| {
6579 const llvm_name = feature.llvm_name orelse continue;
6580 const index: std.Target.Cpu.Feature.Set.Index = @intCast(index_usize);
6581 const is_enabled = cpu.features.isEnabled(index);
6582 const plus_or_minus = "-+"[@intFromBool(is_enabled)];
6583 try stdout_bw.print("{c}{s}\n", .{ plus_or_minus, llvm_name });
6584 }
6585
6586 try stdout_bw.flush();
6587}
6588
6589fn cmdDumpLlvmInts(
6590 gpa: Allocator,
6591 arena: Allocator,
6592 io: Io,
6593 args: []const []const u8,
6594) !void {
6595 dev.check(.llvm_ints_command);
6596
6597 _ = gpa;
6598
6599 if (!build_options.have_llvm)
6600 fatal("compiler does not use LLVM; cannot dump LLVM integer sizes", .{});
6601
6602 const triple = try arena.dupeSentinel(u8, args[0], 0);
6603
6604 const llvm = @import("codegen/llvm/bindings.zig");
6605
6606 for ([_]std.Target.Cpu.Arch{ .aarch64, .x86 }) |arch| {
6607 @import("codegen/llvm.zig").initializeLLVMTarget(arch);
6608 }
6609
6610 const target: *llvm.Target = t: {
6611 var target: *llvm.Target = undefined;
6612 var error_message: [*:0]const u8 = undefined;
6613 if (llvm.Target.getFromTriple(triple, &target, &error_message) != .False) @panic("bad");
6614 break :t target;
6615 };
6616 const tm = llvm.TargetMachine.create(target, triple, null, null, .None, .Default, .Default, false, false, .Default, null, false);
6617 const dl = tm.createTargetDataLayout();
6618 const context = llvm.Context.create();
6619
6620 var stdout_writer = Io.File.stdout().writerStreaming(io, &stdout_buffer);
6621 const stdout_bw = &stdout_writer.interface;
6622 for ([_]u16{ 1, 8, 16, 32, 64, 128, 256 }) |bits| {
6623 const int_type = context.intType(bits);
6624 const alignment = dl.abiAlignmentOfType(int_type);
6625 try stdout_bw.print("LLVMABIAlignmentOfType(i{d}) == {d}\n", .{ bits, alignment });
6626 }
6627 try stdout_bw.flush();
6628
6629 return cleanExit(io);
6630}
6631
66326450/// This is only enabled for debug builds.
66336451fn cmdDumpZir(arena: Allocator, io: Io, args: []const []const u8) !void {
66346452 dev.check(.dump_zir_command);