diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2024-05-09 01:52:26 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2024-05-09 01:52:26 -0700 |
| commit | bcb534c295d5cc6fd63caa570cc08e6b148a507c (patch) | |
| tree | 0b17cb1e632d894f50f25e550d5113f232b0e877 /src/main.zig | |
| parent | d9b00ee4ba48717ff6b306a6f9419e7b604ac04b (diff) | |
| parent | 74f52954b9cb40d59d80b839b45bb859146731a7 (diff) | |
| download | zig-bcb534c295d5cc6fd63caa570cc08e6b148a507c.tar.gz zig-bcb534c295d5cc6fd63caa570cc08e6b148a507c.zip | |
Merge branch 'llvm18'
Upgrades the LLVM, Clang, and LLD dependencies to LLVM 18.x
Related to #16270
Diffstat (limited to 'src/main.zig')
| -rw-r--r-- | src/main.zig | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/src/main.zig b/src/main.zig index 0541d78cd9..7e6b5d261f 100644 --- a/src/main.zig +++ b/src/main.zig @@ -117,6 +117,8 @@ const debug_usage = normal_usage ++ \\ \\ changelist Compute mappings from old ZIR to new ZIR \\ dump-zir Dump a file containing cached ZIR + \\ detect-cpu Compare Zig's CPU feature detection vs LLVM + \\ llvm-ints Dump a list of LLVMABIAlignmentOfType for all integers \\ ; @@ -352,10 +354,14 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { return io.getStdOut().writeAll(usage); } else if (mem.eql(u8, cmd, "ast-check")) { return cmdAstCheck(gpa, arena, cmd_args); + } else if (mem.eql(u8, cmd, "detect-cpu")) { + return cmdDetectCpu(gpa, arena, cmd_args); } else if (build_options.enable_debug_extensions and mem.eql(u8, cmd, "changelist")) { return cmdChangelist(gpa, arena, cmd_args); } else if (build_options.enable_debug_extensions and mem.eql(u8, cmd, "dump-zir")) { return cmdDumpZir(gpa, arena, cmd_args); + } else if (build_options.enable_debug_extensions and mem.eql(u8, cmd, "llvm-ints")) { + return cmdDumpLlvmInts(gpa, arena, cmd_args); } else { std.log.info("{s}", .{usage}); fatal("unknown command: {s}", .{args[1]}); @@ -6150,6 +6156,187 @@ fn cmdAstCheck( return @import("print_zir.zig").renderAsTextToFile(gpa, &file, io.getStdOut()); } +fn cmdDetectCpu( + gpa: Allocator, + arena: Allocator, + args: []const []const u8, +) !void { + _ = gpa; + _ = arena; + + const detect_cpu_usage = + \\Usage: zig detect-cpu [--llvm] + \\ + \\ Print the host CPU name and feature set to stdout. + \\ + \\Options: + \\ -h, --help Print this help and exit + \\ --llvm Detect using LLVM API + \\ + ; + + var use_llvm = false; + + { + var i: usize = 0; + while (i < args.len) : (i += 1) { + const arg = args[i]; + if (mem.startsWith(u8, arg, "-")) { + if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) { + const stdout = io.getStdOut().writer(); + try stdout.writeAll(detect_cpu_usage); + return cleanExit(); + } else if (mem.eql(u8, arg, "--llvm")) { + use_llvm = true; + } else { + fatal("unrecognized parameter: '{s}'", .{arg}); + } + } else { + fatal("unexpected extra parameter: '{s}'", .{arg}); + } + } + } + + if (use_llvm) { + if (!build_options.have_llvm) + fatal("compiler does not use LLVM; cannot compare CPU features with LLVM", .{}); + + const llvm = @import("codegen/llvm/bindings.zig"); + const name = llvm.GetHostCPUName() orelse fatal("LLVM could not figure out the host cpu name", .{}); + const features = llvm.GetHostCPUFeatures() orelse fatal("LLVM could not figure out the host cpu feature set", .{}); + const cpu = try detectNativeCpuWithLLVM(builtin.cpu.arch, name, features); + try printCpu(cpu); + } else { + const host_target = std.zig.resolveTargetQueryOrFatal(.{}); + try printCpu(host_target.cpu); + } +} + +fn detectNativeCpuWithLLVM( + arch: std.Target.Cpu.Arch, + llvm_cpu_name_z: ?[*:0]const u8, + llvm_cpu_features_opt: ?[*:0]const u8, +) !std.Target.Cpu { + var result = std.Target.Cpu.baseline(arch); + + if (llvm_cpu_name_z) |cpu_name_z| { + const llvm_cpu_name = mem.span(cpu_name_z); + + for (arch.allCpuModels()) |model| { + const this_llvm_name = model.llvm_name orelse continue; + if (mem.eql(u8, this_llvm_name, llvm_cpu_name)) { + // Here we use the non-dependencies-populated set, + // so that subtracting features later in this function + // affect the prepopulated set. + result = std.Target.Cpu{ + .arch = arch, + .model = model, + .features = model.features, + }; + break; + } + } + } + + const all_features = arch.allFeaturesList(); + + if (llvm_cpu_features_opt) |llvm_cpu_features| { + var it = mem.tokenizeScalar(u8, mem.span(llvm_cpu_features), ','); + while (it.next()) |decorated_llvm_feat| { + var op: enum { + add, + sub, + } = undefined; + var llvm_feat: []const u8 = undefined; + if (mem.startsWith(u8, decorated_llvm_feat, "+")) { + op = .add; + llvm_feat = decorated_llvm_feat[1..]; + } else if (mem.startsWith(u8, decorated_llvm_feat, "-")) { + op = .sub; + llvm_feat = decorated_llvm_feat[1..]; + } else { + return error.InvalidLlvmCpuFeaturesFormat; + } + for (all_features, 0..) |feature, index_usize| { + const this_llvm_name = feature.llvm_name orelse continue; + if (mem.eql(u8, llvm_feat, this_llvm_name)) { + const index: std.Target.Cpu.Feature.Set.Index = @intCast(index_usize); + switch (op) { + .add => result.features.addFeature(index), + .sub => result.features.removeFeature(index), + } + break; + } + } + } + } + + result.features.populateDependencies(all_features); + return result; +} + +fn printCpu(cpu: std.Target.Cpu) !void { + var bw = io.bufferedWriter(io.getStdOut().writer()); + const stdout = bw.writer(); + + if (cpu.model.llvm_name) |llvm_name| { + try stdout.print("{s}\n", .{llvm_name}); + } + + const all_features = cpu.arch.allFeaturesList(); + for (all_features, 0..) |feature, index_usize| { + const llvm_name = feature.llvm_name orelse continue; + const index: std.Target.Cpu.Feature.Set.Index = @intCast(index_usize); + const is_enabled = cpu.features.isEnabled(index); + const plus_or_minus = "-+"[@intFromBool(is_enabled)]; + try stdout.print("{c}{s}\n", .{ plus_or_minus, llvm_name }); + } + + try bw.flush(); +} + +fn cmdDumpLlvmInts( + gpa: Allocator, + arena: Allocator, + args: []const []const u8, +) !void { + _ = gpa; + + if (!build_options.have_llvm) + fatal("compiler does not use LLVM; cannot dump LLVM integer sizes", .{}); + + const triple = try arena.dupeZ(u8, args[0]); + + const llvm = @import("codegen/llvm/bindings.zig"); + + for ([_]std.Target.Cpu.Arch{ .aarch64, .x86 }) |arch| { + @import("codegen/llvm.zig").initializeLLVMTarget(arch); + } + + const target: *llvm.Target = t: { + var target: *llvm.Target = undefined; + var error_message: [*:0]const u8 = undefined; + if (llvm.Target.getFromTriple(triple, &target, &error_message) != .False) @panic("bad"); + break :t target; + }; + const tm = llvm.TargetMachine.create(target, triple, null, null, .None, .Default, .Default, false, false, .Default, null); + const dl = tm.createTargetDataLayout(); + const context = llvm.Context.create(); + + var bw = io.bufferedWriter(io.getStdOut().writer()); + const stdout = bw.writer(); + + for ([_]u16{ 1, 8, 16, 32, 64, 128, 256 }) |bits| { + const int_type = context.intType(bits); + const alignment = dl.abiAlignmentOfType(int_type); + try stdout.print("LLVMABIAlignmentOfType(i{d}) == {d}\n", .{ bits, alignment }); + } + + try bw.flush(); + + return cleanExit(); +} + /// This is only enabled for debug builds. fn cmdDumpZir( gpa: Allocator, |
