| ... | @@ -125,8 +125,6 @@ const debug_usage = normal_usage ++ | ... | @@ -125,8 +125,6 @@ const debug_usage = normal_usage ++ |
| 125 | \\ | 125 | \\ |
| 126 | \\ changelist Compute mappings from old ZIR to new ZIR | 126 | \\ changelist Compute mappings from old ZIR to new ZIR |
| 127 | \\ dump-zir Dump a file containing cached ZIR | 127 | \\ 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 | | |
| 130 | \\ | 128 | \\ |
| 131 | ; | 129 | ; |
| 132 | | 130 | |
| ... | @@ -403,14 +401,10 @@ fn mainArgs( | ... | @@ -403,14 +401,10 @@ fn mainArgs( |
| 403 | return Io.File.stdout().writeStreamingAll(io, usage); | 401 | return Io.File.stdout().writeStreamingAll(io, usage); |
| 404 | } else if (mem.eql(u8, cmd, "ast-check")) { | 402 | } else if (mem.eql(u8, cmd, "ast-check")) { |
| 405 | return cmdAstCheck(arena, io, cmd_args); | 403 | return cmdAstCheck(arena, io, cmd_args); |
| 406 | } else if (mem.eql(u8, cmd, "detect-cpu")) { | | |
| 407 | return cmdDetectCpu(io, cmd_args); | | |
| 408 | } else if (build_options.enable_debug_extensions and mem.eql(u8, cmd, "changelist")) { | 404 | } else if (build_options.enable_debug_extensions and mem.eql(u8, cmd, "changelist")) { |
| 409 | return cmdChangelist(arena, io, cmd_args); | 405 | return cmdChangelist(arena, io, cmd_args); |
| 410 | } else if (build_options.enable_debug_extensions and mem.eql(u8, cmd, "dump-zir")) { | 406 | } else if (build_options.enable_debug_extensions and mem.eql(u8, cmd, "dump-zir")) { |
| 411 | return cmdDumpZir(arena, io, cmd_args); | 407 | 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); | | |
| 414 | } else { | 408 | } else { |
| 415 | std.log.info("{s}", .{usage}); | 409 | std.log.info("{s}", .{usage}); |
| 416 | fatal("unknown command: {s}", .{args[1]}); | 410 | fatal("unknown command: {s}", .{args[1]}); |
| ... | @@ -6453,182 +6447,6 @@ fn cmdAstCheck(arena: Allocator, io: Io, args: []const []const u8) !void { | ... | @@ -6453,182 +6447,6 @@ fn cmdAstCheck(arena: Allocator, io: Io, args: []const []const u8) !void { |
| 6453 | } | 6447 | } |
| 6454 | } | 6448 | } |
| 6455 | | 6449 | |
| 6456 | fn 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 | | | |
| 6506 | fn 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 | | | |
| 6569 | fn 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 | | | |
| 6589 | fn 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 | | | |
| 6632 | /// This is only enabled for debug builds. | 6450 | /// This is only enabled for debug builds. |
| 6633 | fn cmdDumpZir(arena: Allocator, io: Io, args: []const []const u8) !void { | 6451 | fn cmdDumpZir(arena: Allocator, io: Io, args: []const []const u8) !void { |
| 6634 | dev.check(.dump_zir_command); | 6452 | dev.check(.dump_zir_command); |