authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-08-24 00:47:19+02:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-08-24 00:47:19+02:00
log87169df9c140435f5651ea98b7f8ffaba56ebaf2
tree3440218bfca50c7dd9ea8bbfbfe0a8933e00932c
parent93510cc95c3a07fc2765f729d149d8e76b2666e6
parentebbe6ef4b3ed2d6168ec76d6541f6c93db15a2f5

Merge pull request 'some miscellaneous `std.Target` stuff' (#36614) from alexrp/zig:std-target-stuff into master

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/36614

9 files changed, 398 insertions(+), 321 deletions(-)

lib/compiler/aro/aro/Target.zig+4-1
......@@ -523,7 +523,10 @@ pub fn systemCompiler(target: *const Target) LangOpts.Compiler {
523523 // the rest for documentation as fn returns .clang
524524 if (target.os.tag.isDarwin() or
525525 target.abi.isAndroid() or
526 target.os.tag.isBSD() or
526 target.os.tag == .dragonfly or
527 target.os.tag == .freebsd or
528 target.os.tag == .netbsd or
529 target.os.tag == .openbsd or
527530 target.os.tag == .fuchsia or
528531 target.os.tag == .illumos or
529532 target.os.tag == .haiku or
lib/std/Target.zig+52-14
......@@ -89,6 +89,7 @@ pub const Os = struct {
8989 };
9090 }
9191
92 /// Deprecated; to be removed in 0.18.0. Check for relevant tags instead.
9293 pub inline fn isBSD(tag: Tag) bool {
9394 return tag.isDarwin() or switch (tag) {
9495 .freebsd, .openbsd, .netbsd, .dragonfly => true,
......@@ -1109,7 +1110,7 @@ pub fn toElfMachine(target: *const Target) std.elf.EM {
11091110 .riscv32, .riscv32be, .riscv64, .riscv64be => .RISCV,
11101111 .s390x => .S390,
11111112 .sh, .sheb => .SH,
1112 .sparc => if (target.cpu.has(.sparc, .v9)) .SPARC32PLUS else .SPARC,
1113 .sparc => if (target.cpu.hasAny(.sparc, &.{ .v8plus, .v9 })) .SPARC32PLUS else .SPARC,
11131114 .sparc64 => .SPARCV9,
11141115 .ve => .VE,
11151116 .x86_16, .x86 => .@"386",
......@@ -1509,7 +1510,10 @@ pub const Cpu = struct {
15091510 };
15101511 }
15111512
1512 pub inline fn isAARCH64(arch: Arch) bool {
1513 /// Deprecated; to be removed in 0.18.0. Use `isAarch64` instead.
1514 pub const isAARCH64 = isAarch64;
1515
1516 pub inline fn isAarch64(arch: Arch) bool {
15131517 return switch (arch) {
15141518 .aarch64, .aarch64_be => true,
15151519 else => false,
......@@ -1537,14 +1541,20 @@ pub const Cpu = struct {
15371541 };
15381542 }
15391543
1540 pub inline fn isLoongArch(arch: Arch) bool {
1544 /// Deprecated; to be removed in 0.18.0. Use `isLoongarch` instead.
1545 pub const isLoongArch = isLoongarch;
1546
1547 pub inline fn isLoongarch(arch: Arch) bool {
15411548 return switch (arch) {
15421549 .loongarch32, .loongarch64 => true,
15431550 else => false,
15441551 };
15451552 }
15461553
1547 pub inline fn isRISCV(arch: Arch) bool {
1554 /// Deprecated; to be removed in 0.18.0. Use `isRiscv` instead.
1555 pub const isRISCV = isRiscv;
1556
1557 pub inline fn isRiscv(arch: Arch) bool {
15481558 return arch.isRiscv32() or arch.isRiscv64();
15491559 }
15501560
......@@ -1569,50 +1579,74 @@ pub const Cpu = struct {
15691579 };
15701580 }
15711581
1572 pub inline fn isMIPS(arch: Arch) bool {
1573 return arch.isMIPS32() or arch.isMIPS64();
1582 /// Deprecated; to be removed in 0.18.0. Use `isMips` instead.
1583 pub const isMIPS = isMips;
1584
1585 pub inline fn isMips(arch: Arch) bool {
1586 return arch.isMips32() or arch.isMips64();
15741587 }
15751588
1576 pub inline fn isMIPS32(arch: Arch) bool {
1589 /// Deprecated; to be removed in 0.18.0. Use `isMips32` instead.
1590 pub const isMIPS32 = isMips32;
1591
1592 pub inline fn isMips32(arch: Arch) bool {
15771593 return switch (arch) {
15781594 .mips, .mipsel => true,
15791595 else => false,
15801596 };
15811597 }
15821598
1583 pub inline fn isMIPS64(arch: Arch) bool {
1599 /// Deprecated; to be removed in 0.18.0. Use `isMips64` instead.
1600 pub const isMIPS64 = isMips64;
1601
1602 pub inline fn isMips64(arch: Arch) bool {
15841603 return switch (arch) {
15851604 .mips64, .mips64el => true,
15861605 else => false,
15871606 };
15881607 }
15891608
1590 pub inline fn isPowerPC(arch: Arch) bool {
1591 return arch.isPowerPC32() or arch.isPowerPC64();
1609 /// Deprecated; to be removed in 0.18.0. Use `isPowerpc` instead.
1610 pub const isPowerPC = isPowerpc;
1611
1612 pub inline fn isPowerpc(arch: Arch) bool {
1613 return arch.isPowerpc32() or arch.isPowerpc64();
15921614 }
15931615
1594 pub inline fn isPowerPC32(arch: Arch) bool {
1616 /// Deprecated; to be removed in 0.18.0. Use `isPowerpc32` instead.
1617 pub const isPowerPC32 = isPowerpc32;
1618
1619 pub inline fn isPowerpc32(arch: Arch) bool {
15951620 return switch (arch) {
15961621 .powerpc, .powerpcle => true,
15971622 else => false,
15981623 };
15991624 }
16001625
1601 pub inline fn isPowerPC64(arch: Arch) bool {
1626 /// Deprecated; to be removed in 0.18.0. Use `isPowerpc64` instead.
1627 pub const isPowerPC64 = isPowerpc64;
1628
1629 pub inline fn isPowerpc64(arch: Arch) bool {
16021630 return switch (arch) {
16031631 .powerpc64, .powerpc64le => true,
16041632 else => false,
16051633 };
16061634 }
16071635
1608 pub inline fn isSPARC(arch: Arch) bool {
1636 /// Deprecated; to be removed in 0.18.0. Use `isSparc` instead.
1637 pub const isSPARC = isSparc;
1638
1639 pub inline fn isSparc(arch: Arch) bool {
16091640 return switch (arch) {
16101641 .sparc, .sparc64 => true,
16111642 else => false,
16121643 };
16131644 }
16141645
1615 pub inline fn isSpirV(arch: Arch) bool {
1646 /// Deprecated; to be removed in 0.18.0. Use `isSpirv` instead.
1647 pub const isSpirV = isSpirv;
1648
1649 pub inline fn isSpirv(arch: Arch) bool {
16161650 return switch (arch) {
16171651 .spirv32, .spirv64 => true,
16181652 else => false,
......@@ -2146,18 +2180,22 @@ pub fn zigTriple(target: *const Target, allocator: Allocator) Allocator.Error![]
21462180 return Query.fromTarget(target).zigTriple(allocator);
21472181}
21482182
2183/// Deprecated; to be removed in 0.18.0. Use `std.zig.target.hurdTupleSimple` instead.
21492184pub fn hurdTupleSimple(allocator: Allocator, arch: Cpu.Arch, abi: Abi) ![]u8 {
21502185 return std.fmt.allocPrint(allocator, "{s}-{s}", .{ @tagName(arch), @tagName(abi) });
21512186}
21522187
2188/// Deprecated; to be removed in 0.18.0. Use `std.zig.target.hurdTuple` instead.
21532189pub fn hurdTuple(target: *const Target, allocator: Allocator) ![]u8 {
21542190 return hurdTupleSimple(allocator, target.cpu.arch, target.abi);
21552191}
21562192
2193/// Deprecated; to be removed in 0.18.0. Use `std.zig.target.linuxTripleSimple` instead.
21572194pub fn linuxTripleSimple(allocator: Allocator, arch: Cpu.Arch, os_tag: Os.Tag, abi: Abi) ![]u8 {
21582195 return std.fmt.allocPrint(allocator, "{s}-{s}-{s}", .{ @tagName(arch), @tagName(os_tag), @tagName(abi) });
21592196}
21602197
2198/// Deprecated; to be removed in 0.18.0. Use `std.zig.target.linuxTriple` instead.
21612199pub fn linuxTriple(target: *const Target, allocator: Allocator) ![]u8 {
21622200 return linuxTripleSimple(allocator, target.cpu.arch, target.os.tag, target.abi);
21632201}
lib/std/zig/llvm/Builder.zig+295-3
......@@ -84,9 +84,300 @@ pub const Options = struct {
8484 strip: bool = true,
8585 name: []const u8 = &.{},
8686 target: *const std.Target = &builtin.target,
87 triple: []const u8 = &.{},
8887};
8988
89fn subArchName(target: *const std.Target, comptime family: std.Target.Cpu.Arch.Family, mappings: anytype) ?[]const u8 {
90 inline for (mappings) |mapping| {
91 if (target.cpu.has(family, mapping[0])) return mapping[1];
92 }
93
94 return null;
95}
96
97pub fn tripleForTarget(allocator: Allocator, target: *const std.Target) ![]const u8 {
98 var llvm_triple = std.array_list.Managed(u8).init(allocator);
99 defer llvm_triple.deinit();
100
101 const llvm_arch = switch (target.cpu.arch) {
102 .arm => "arm",
103 .armeb => "armeb",
104 .aarch64 => if (target.abi == .ilp32) "aarch64_32" else "aarch64",
105 .aarch64_be => "aarch64_be",
106 .arc => "arc",
107 .avr => "avr",
108 .bpfel => "bpfel",
109 .bpfeb => "bpfeb",
110 .csky => "csky",
111 .hexagon => "hexagon",
112 .loongarch32 => "loongarch32",
113 .loongarch64 => "loongarch64",
114 .m68k => "m68k",
115 // MIPS sub-architectures are a bit irregular, so we handle them manually here.
116 .mips => if (target.cpu.has(.mips, .mips32r6)) "mipsisa32r6" else "mips",
117 .mipsel => if (target.cpu.has(.mips, .mips32r6)) "mipsisa32r6el" else "mipsel",
118 .mips64 => if (target.cpu.has(.mips, .mips64r6)) "mipsisa64r6" else "mips64",
119 .mips64el => if (target.cpu.has(.mips, .mips64r6)) "mipsisa64r6el" else "mips64el",
120 .msp430 => "msp430",
121 .powerpc => "powerpc",
122 .powerpcle => "powerpcle",
123 .powerpc64 => "powerpc64",
124 .powerpc64le => "powerpc64le",
125 .amdgcn => "amdgcn",
126 .riscv32 => "riscv32",
127 .riscv32be => "riscv32be",
128 .riscv64 => "riscv64",
129 .riscv64be => "riscv64be",
130 .sparc => "sparc",
131 .sparc64 => "sparc64",
132 .s390x => "s390x",
133 .thumb => "thumb",
134 .thumbeb => "thumbeb",
135 .x86 => "i386",
136 .x86_64 => "x86_64",
137 .xcore => "xcore",
138 .xtensa => "xtensa",
139 .nvptx => "nvptx",
140 .nvptx64 => "nvptx64",
141 .spirv32 => switch (target.os.tag) {
142 .vulkan, .opengl => "spirv",
143 else => "spirv32",
144 },
145 .spirv64 => "spirv64",
146 .lanai => "lanai",
147 .wasm32 => "wasm32",
148 .wasm64 => "wasm64",
149 .ve => "ve",
150
151 .alpha,
152 .arceb,
153 .ez80,
154 .hppa,
155 .hppa64,
156 .kalimba,
157 .kvx,
158 .m88k,
159 .microblaze,
160 .microblazeel,
161 .or1k,
162 .propeller,
163 .sh,
164 .sheb,
165 .x86_16,
166 .xtensaeb,
167 => unreachable, // Gated by hasLlvmSupport().
168 };
169
170 try llvm_triple.appendSlice(llvm_arch);
171
172 const llvm_sub_arch: ?[]const u8 = switch (target.cpu.arch) {
173 .arm, .armeb, .thumb, .thumbeb => subArchName(target, .arm, .{
174 .{ .v4t, "v4t" },
175 .{ .v5t, "v5t" },
176 .{ .v5te, "v5te" },
177 .{ .v5tej, "v5tej" },
178 .{ .v6, "v6" },
179 .{ .v6k, "v6k" },
180 .{ .v6kz, "v6kz" },
181 .{ .v6m, "v6m" },
182 .{ .v6t2, "v6t2" },
183 .{ .v7a, "v7a" },
184 .{ .v7em, "v7em" },
185 .{ .v7m, "v7m" },
186 .{ .v7r, "v7r" },
187 .{ .v7ve, "v7ve" },
188 .{ .v8a, "v8a" },
189 .{ .v8_1a, "v8.1a" },
190 .{ .v8_2a, "v8.2a" },
191 .{ .v8_3a, "v8.3a" },
192 .{ .v8_4a, "v8.4a" },
193 .{ .v8_5a, "v8.5a" },
194 .{ .v8_6a, "v8.6a" },
195 .{ .v8_7a, "v8.7a" },
196 .{ .v8_8a, "v8.8a" },
197 .{ .v8_9a, "v8.9a" },
198 .{ .v8m, "v8m.base" },
199 .{ .v8m_main, "v8m.main" },
200 .{ .v8_1m_main, "v8.1m.main" },
201 .{ .v8r, "v8r" },
202 .{ .v9a, "v9a" },
203 .{ .v9_1a, "v9.1a" },
204 .{ .v9_2a, "v9.2a" },
205 .{ .v9_3a, "v9.3a" },
206 .{ .v9_4a, "v9.4a" },
207 .{ .v9_5a, "v9.5a" },
208 .{ .v9_6a, "v9.6a" },
209 .{ .v9_7a, "v9.7a" },
210 }),
211 .powerpc => subArchName(target, .powerpc, .{
212 .{ .spe, "spe" },
213 }),
214 .spirv32, .spirv64 => subArchName(target, .spirv, .{
215 .{ .v1_6, "1.6" },
216 .{ .v1_5, "1.5" },
217 .{ .v1_4, "1.4" },
218 .{ .v1_3, "1.3" },
219 .{ .v1_2, "1.2" },
220 .{ .v1_1, "1.1" },
221 }),
222 else => null,
223 };
224
225 if (llvm_sub_arch) |sub| try llvm_triple.appendSlice(sub);
226 try llvm_triple.append('-');
227
228 try llvm_triple.appendSlice(switch (target.os.tag) {
229 .driverkit,
230 .ios,
231 .maccatalyst,
232 .macos,
233 .tvos,
234 .visionos,
235 .watchos,
236 => "apple",
237 .ps4,
238 .ps5,
239 => "scei",
240 .amdhsa,
241 .amdpal,
242 => "amd",
243 .cuda,
244 .nvcl,
245 => "nvidia",
246 .mesa3d,
247 => "mesa",
248 else => "unknown",
249 });
250 try llvm_triple.append('-');
251
252 const llvm_os = switch (target.os.tag) {
253 .dragonfly => "dragonfly",
254 .freebsd => "freebsd",
255 .fuchsia => "fuchsia",
256 .linux => "linux",
257 .netbsd => "netbsd",
258 .openbsd => "openbsd",
259 .illumos => "solaris",
260 .windows, .uefi => "windows",
261 .haiku => "haiku",
262 .rtems => "rtems",
263 .cuda => "cuda",
264 .nvcl => "nvcl",
265 .amdhsa => "amdhsa",
266 .ps3 => "lv2",
267 .ps4 => "ps4",
268 .ps5 => "ps5",
269 .mesa3d => "mesa3d",
270 .amdpal => "amdpal",
271 .hermit => "hermit",
272 .hurd => "hurd",
273 .wasi => "wasi",
274 .emscripten => "emscripten",
275 .macos => "macosx",
276 .ios, .maccatalyst => "ios",
277 .tvos => "tvos",
278 .watchos => "watchos",
279 .driverkit => "driverkit",
280 .visionos => "xros",
281 .serenity => "serenity",
282 .vulkan => "vulkan",
283 .managarm => "managarm",
284
285 .contiki,
286 .freestanding,
287 .opencl, // https://llvm.org/docs/SPIRVUsage.html#target-triples
288 .opengl,
289 .other,
290 .plan9,
291 .psx,
292 .psp,
293 .vita,
294 .tios,
295 .@"3ds",
296 .wiiu,
297 .@"switch",
298 .ashetos,
299 => "unknown",
300 };
301 try llvm_triple.appendSlice(llvm_os);
302
303 switch (target.os.versionRange()) {
304 .none,
305 .windows,
306 => {},
307 .semver => |ver| if (target.os.tag == .wasi and ver.min.major == 0) {
308 try llvm_triple.print("p{d}", .{ver.min.minor});
309 } else if (target.os.tag != .amdhsa) {
310 try llvm_triple.print("{d}.{d}.{d}", .{
311 ver.min.major,
312 ver.min.minor,
313 ver.min.patch,
314 });
315 },
316 inline .linux, .hurd => |ver| try llvm_triple.print("{d}.{d}.{d}", .{
317 ver.range.min.major,
318 ver.range.min.minor,
319 ver.range.min.patch,
320 }),
321 }
322 try llvm_triple.append('-');
323
324 const llvm_abi = switch (target.abi) {
325 .none => if (target.os.tag == .maccatalyst) "macabi" else "unknown",
326 .gnu => "gnu",
327 .gnuabin32 => "gnuabin32",
328 .gnuabi64 => "gnuabi64",
329 .gnueabi => "gnueabi",
330 .gnueabihf => "gnueabihf",
331 .gnuf32 => "gnuf32",
332 .gnusf => "gnusf",
333 .gnux32 => "gnux32",
334 .ilp32 => "unknown",
335 .eabi => "eabi",
336 .eabihf => "eabihf",
337 .abin32 => "unknown",
338 .x32 => "muslx32", // https://github.com/ziglang/zig/issues/25649
339 .android => "android",
340 .androideabi => "androideabi",
341 .musl => switch (target.os.tag) {
342 // For WASI/Emscripten, "musl" refers to the libc, not really the ABI.
343 // "unknown" provides better compatibility with LLVM-based tooling for these targets.
344 .wasi, .emscripten => "unknown",
345 else => "musl",
346 },
347 .muslabin32 => "muslabin32",
348 .muslabi64 => "muslabi64",
349 .musleabi => "musleabi",
350 .musleabihf => "musleabihf",
351 .muslf32 => "muslf32",
352 .muslsf => "muslsf",
353 .muslx32 => "muslx32",
354 .msvc => "msvc",
355 .itanium => "itanium",
356 .simulator => "simulator",
357 .ohos, .ohoseabi => "ohos",
358 .call0 => "unknown",
359 };
360 try llvm_triple.appendSlice(llvm_abi);
361
362 switch (target.os.versionRange()) {
363 .none,
364 .semver,
365 .windows,
366 => {},
367 inline .hurd, .linux => |ver| if (target.abi.isGnu()) {
368 try llvm_triple.print("{d}.{d}.{d}", .{
369 ver.glibc.major,
370 ver.glibc.minor,
371 ver.glibc.patch,
372 });
373 } else if (@TypeOf(ver) == std.Target.Os.LinuxVersionRange and target.abi.isAndroid()) {
374 try llvm_triple.print("{d}", .{ver.android});
375 },
376 }
377
378 return llvm_triple.toOwnedSlice();
379}
380
90381pub const DataLayout = struct {
91382 endian: ?std.lang.Endian,
92383 int_specs: PrimitiveSpec.Map,
......@@ -9610,6 +9901,9 @@ pub fn init(options: Options) Allocator.Error!Builder {
96109901 try self.string_indices.append(self.gpa, 0);
96119902 assert(try self.string("") == .empty);
96129903
9904 const llvm_triple = try tripleForTarget(self.gpa, options.target);
9905 defer self.gpa.free(llvm_triple);
9906 self.target_triple = try self.string(llvm_triple);
96139907 self.data_layout = try .parseString(try self.string(DataLayout.stringForTarget(options.target)), &self);
96149908
96159909 try self.strtab_string_indices.append(self.gpa, 0);
......@@ -9617,8 +9911,6 @@ pub fn init(options: Options) Allocator.Error!Builder {
96179911
96189912 if (options.name.len > 0) self.source_filename = try self.string(options.name);
96199913
9620 if (options.triple.len > 0) self.target_triple = try self.string(options.triple);
9621
96229914 {
96239915 const static_len = @typeInfo(Type).@"enum".field_names.len - 1;
96249916 try self.type_map.ensureTotalCapacity(self.gpa, static_len);
lib/std/zig/system/NativePaths.zig+1-1
......@@ -149,7 +149,7 @@ pub fn detect(
149149 }
150150
151151 if (builtin.os.tag != .windows and builtin.os.tag != .wasi) {
152 const triple = try native_target.linuxTriple(arena);
152 const triple = try std.zig.target.linuxTriple(arena, native_target);
153153
154154 const qual = native_target.ptrBitWidth();
155155
lib/std/zig/target.zig+28-3
......@@ -143,6 +143,31 @@ pub fn canBuildLibC(target: *const std.Target) bool {
143143 return false;
144144}
145145
146pub fn hurdTupleSimple(
147 allocator: Allocator,
148 arch: std.Target.Cpu.Arch,
149 abi: std.Target.Abi,
150) ![]u8 {
151 return std.fmt.allocPrint(allocator, "{s}-{s}", .{ @tagName(arch), @tagName(abi) });
152}
153
154pub fn hurdTuple(allocator: Allocator, target: *const std.Target) ![]u8 {
155 return hurdTupleSimple(allocator, target.cpu.arch, target.abi);
156}
157
158pub fn linuxTripleSimple(
159 allocator: Allocator,
160 arch: std.Target.Cpu.Arch,
161 os_tag: std.Target.Os.Tag,
162 abi: std.Target.Abi,
163) ![]u8 {
164 return std.fmt.allocPrint(allocator, "{s}-{s}-{s}", .{ @tagName(arch), @tagName(os_tag), @tagName(abi) });
165}
166
167pub fn linuxTriple(allocator: Allocator, target: *const std.Target) ![]u8 {
168 return linuxTripleSimple(allocator, target.cpu.arch, target.os.tag, target.abi);
169}
170
146171/// Returns the subdirectory triple to be used to find the correct glibc for the given `arch`, `os`,
147172/// and `abi` in an installation directory created by glibc's `build-many-glibcs.py` script.
148173///
......@@ -162,8 +187,8 @@ pub fn glibcRuntimeTriple(
162187 }
163188
164189 return switch (os) {
165 .hurd => std.Target.hurdTupleSimple(allocator, arch, abi),
166 .linux => std.Target.linuxTripleSimple(allocator, arch, os, abi),
190 .hurd => hurdTupleSimple(allocator, arch, abi),
191 .linux => linuxTripleSimple(allocator, arch, os, abi),
167192 else => unreachable,
168193 };
169194}
......@@ -179,7 +204,7 @@ pub fn muslRuntimeTriple(
179204) Allocator.Error![]const u8 {
180205 assert(abi.isMusl());
181206
182 return std.Target.linuxTripleSimple(allocator, arch, .linux, abi);
207 return linuxTripleSimple(allocator, arch, .linux, abi);
183208}
184209
185210pub fn osArchName(target: *const std.Target) [:0]const u8 {
src/Compilation.zig+1-1
......@@ -6574,7 +6574,7 @@ pub fn addCCArgs(
65746574 try argv.append("-integrated-as");
65756575 }
65766576
6577 const llvm_triple = try @import("codegen/llvm.zig").targetTriple(arena, target);
6577 const llvm_triple = try std.zig.llvm.Builder.tripleForTarget(arena, target);
65786578 try argv.appendSlice(&[_][]const u8{ "-target", llvm_triple });
65796579
65806580 if (target.cpu.arch.isThumb()) {
src/codegen/llvm.zig-294
......@@ -46,298 +46,6 @@ pub fn legalizeFeatures(target: *const std.Target) ?*const Air.Legalize.Features
4646 };
4747}
4848
49fn subArchName(target: *const std.Target, comptime family: std.Target.Cpu.Arch.Family, mappings: anytype) ?[]const u8 {
50 inline for (mappings) |mapping| {
51 if (target.cpu.has(family, mapping[0])) return mapping[1];
52 }
53
54 return null;
55}
56
57pub fn targetTriple(allocator: Allocator, target: *const std.Target) ![]const u8 {
58 var llvm_triple = std.array_list.Managed(u8).init(allocator);
59 defer llvm_triple.deinit();
60
61 const llvm_arch = switch (target.cpu.arch) {
62 .arm => "arm",
63 .armeb => "armeb",
64 .aarch64 => if (target.abi == .ilp32) "aarch64_32" else "aarch64",
65 .aarch64_be => "aarch64_be",
66 .arc => "arc",
67 .avr => "avr",
68 .bpfel => "bpfel",
69 .bpfeb => "bpfeb",
70 .csky => "csky",
71 .hexagon => "hexagon",
72 .loongarch32 => "loongarch32",
73 .loongarch64 => "loongarch64",
74 .m68k => "m68k",
75 // MIPS sub-architectures are a bit irregular, so we handle them manually here.
76 .mips => if (target.cpu.has(.mips, .mips32r6)) "mipsisa32r6" else "mips",
77 .mipsel => if (target.cpu.has(.mips, .mips32r6)) "mipsisa32r6el" else "mipsel",
78 .mips64 => if (target.cpu.has(.mips, .mips64r6)) "mipsisa64r6" else "mips64",
79 .mips64el => if (target.cpu.has(.mips, .mips64r6)) "mipsisa64r6el" else "mips64el",
80 .msp430 => "msp430",
81 .powerpc => "powerpc",
82 .powerpcle => "powerpcle",
83 .powerpc64 => "powerpc64",
84 .powerpc64le => "powerpc64le",
85 .amdgcn => "amdgcn",
86 .riscv32 => "riscv32",
87 .riscv32be => "riscv32be",
88 .riscv64 => "riscv64",
89 .riscv64be => "riscv64be",
90 .sparc => "sparc",
91 .sparc64 => "sparc64",
92 .s390x => "s390x",
93 .thumb => "thumb",
94 .thumbeb => "thumbeb",
95 .x86 => "i386",
96 .x86_64 => "x86_64",
97 .xcore => "xcore",
98 .xtensa => "xtensa",
99 .nvptx => "nvptx",
100 .nvptx64 => "nvptx64",
101 .spirv32 => switch (target.os.tag) {
102 .vulkan, .opengl => "spirv",
103 else => "spirv32",
104 },
105 .spirv64 => "spirv64",
106 .lanai => "lanai",
107 .wasm32 => "wasm32",
108 .wasm64 => "wasm64",
109 .ve => "ve",
110
111 .alpha,
112 .arceb,
113 .ez80,
114 .hppa,
115 .hppa64,
116 .kalimba,
117 .kvx,
118 .m88k,
119 .microblaze,
120 .microblazeel,
121 .or1k,
122 .propeller,
123 .sh,
124 .sheb,
125 .x86_16,
126 .xtensaeb,
127 => unreachable, // Gated by hasLlvmSupport().
128 };
129
130 try llvm_triple.appendSlice(llvm_arch);
131
132 const llvm_sub_arch: ?[]const u8 = switch (target.cpu.arch) {
133 .arm, .armeb, .thumb, .thumbeb => subArchName(target, .arm, .{
134 .{ .v4t, "v4t" },
135 .{ .v5t, "v5t" },
136 .{ .v5te, "v5te" },
137 .{ .v5tej, "v5tej" },
138 .{ .v6, "v6" },
139 .{ .v6k, "v6k" },
140 .{ .v6kz, "v6kz" },
141 .{ .v6m, "v6m" },
142 .{ .v6t2, "v6t2" },
143 .{ .v7a, "v7a" },
144 .{ .v7em, "v7em" },
145 .{ .v7m, "v7m" },
146 .{ .v7r, "v7r" },
147 .{ .v7ve, "v7ve" },
148 .{ .v8a, "v8a" },
149 .{ .v8_1a, "v8.1a" },
150 .{ .v8_2a, "v8.2a" },
151 .{ .v8_3a, "v8.3a" },
152 .{ .v8_4a, "v8.4a" },
153 .{ .v8_5a, "v8.5a" },
154 .{ .v8_6a, "v8.6a" },
155 .{ .v8_7a, "v8.7a" },
156 .{ .v8_8a, "v8.8a" },
157 .{ .v8_9a, "v8.9a" },
158 .{ .v8m, "v8m.base" },
159 .{ .v8m_main, "v8m.main" },
160 .{ .v8_1m_main, "v8.1m.main" },
161 .{ .v8r, "v8r" },
162 .{ .v9a, "v9a" },
163 .{ .v9_1a, "v9.1a" },
164 .{ .v9_2a, "v9.2a" },
165 .{ .v9_3a, "v9.3a" },
166 .{ .v9_4a, "v9.4a" },
167 .{ .v9_5a, "v9.5a" },
168 .{ .v9_6a, "v9.6a" },
169 .{ .v9_7a, "v9.7a" },
170 }),
171 .powerpc => subArchName(target, .powerpc, .{
172 .{ .spe, "spe" },
173 }),
174 .spirv32, .spirv64 => subArchName(target, .spirv, .{
175 .{ .v1_6, "1.6" },
176 .{ .v1_5, "1.5" },
177 .{ .v1_4, "1.4" },
178 .{ .v1_3, "1.3" },
179 .{ .v1_2, "1.2" },
180 .{ .v1_1, "1.1" },
181 }),
182 else => null,
183 };
184
185 if (llvm_sub_arch) |sub| try llvm_triple.appendSlice(sub);
186 try llvm_triple.append('-');
187
188 try llvm_triple.appendSlice(switch (target.os.tag) {
189 .driverkit,
190 .ios,
191 .maccatalyst,
192 .macos,
193 .tvos,
194 .visionos,
195 .watchos,
196 => "apple",
197 .ps4,
198 .ps5,
199 => "scei",
200 .amdhsa,
201 .amdpal,
202 => "amd",
203 .cuda,
204 .nvcl,
205 => "nvidia",
206 .mesa3d,
207 => "mesa",
208 else => "unknown",
209 });
210 try llvm_triple.append('-');
211
212 const llvm_os = switch (target.os.tag) {
213 .dragonfly => "dragonfly",
214 .freebsd => "freebsd",
215 .fuchsia => "fuchsia",
216 .linux => "linux",
217 .netbsd => "netbsd",
218 .openbsd => "openbsd",
219 .illumos => "solaris",
220 .windows, .uefi => "windows",
221 .haiku => "haiku",
222 .rtems => "rtems",
223 .cuda => "cuda",
224 .nvcl => "nvcl",
225 .amdhsa => "amdhsa",
226 .ps3 => "lv2",
227 .ps4 => "ps4",
228 .ps5 => "ps5",
229 .mesa3d => "mesa3d",
230 .amdpal => "amdpal",
231 .hermit => "hermit",
232 .hurd => "hurd",
233 .wasi => "wasi",
234 .emscripten => "emscripten",
235 .macos => "macosx",
236 .ios, .maccatalyst => "ios",
237 .tvos => "tvos",
238 .watchos => "watchos",
239 .driverkit => "driverkit",
240 .visionos => "xros",
241 .serenity => "serenity",
242 .vulkan => "vulkan",
243 .managarm => "managarm",
244
245 .contiki,
246 .freestanding,
247 .opencl, // https://llvm.org/docs/SPIRVUsage.html#target-triples
248 .opengl,
249 .other,
250 .plan9,
251 .psx,
252 .psp,
253 .vita,
254 .tios,
255 .@"3ds",
256 .wiiu,
257 .@"switch",
258 .ashetos,
259 => "unknown",
260 };
261 try llvm_triple.appendSlice(llvm_os);
262
263 switch (target.os.versionRange()) {
264 .none,
265 .windows,
266 => {},
267 .semver => |ver| if (target.os.tag == .wasi and ver.min.major == 0) {
268 try llvm_triple.print("p{d}", .{ver.min.minor});
269 } else if (target.os.tag != .amdhsa) {
270 try llvm_triple.print("{d}.{d}.{d}", .{
271 ver.min.major,
272 ver.min.minor,
273 ver.min.patch,
274 });
275 },
276 inline .linux, .hurd => |ver| try llvm_triple.print("{d}.{d}.{d}", .{
277 ver.range.min.major,
278 ver.range.min.minor,
279 ver.range.min.patch,
280 }),
281 }
282 try llvm_triple.append('-');
283
284 const llvm_abi = switch (target.abi) {
285 .none => if (target.os.tag == .maccatalyst) "macabi" else "unknown",
286 .gnu => "gnu",
287 .gnuabin32 => "gnuabin32",
288 .gnuabi64 => "gnuabi64",
289 .gnueabi => "gnueabi",
290 .gnueabihf => "gnueabihf",
291 .gnuf32 => "gnuf32",
292 .gnusf => "gnusf",
293 .gnux32 => "gnux32",
294 .ilp32 => "unknown",
295 .eabi => "eabi",
296 .eabihf => "eabihf",
297 .abin32 => "unknown",
298 .x32 => "muslx32", // https://github.com/ziglang/zig/issues/25649
299 .android => "android",
300 .androideabi => "androideabi",
301 .musl => switch (target.os.tag) {
302 // For WASI/Emscripten, "musl" refers to the libc, not really the ABI.
303 // "unknown" provides better compatibility with LLVM-based tooling for these targets.
304 .wasi, .emscripten => "unknown",
305 else => "musl",
306 },
307 .muslabin32 => "muslabin32",
308 .muslabi64 => "muslabi64",
309 .musleabi => "musleabi",
310 .musleabihf => "musleabihf",
311 .muslf32 => "muslf32",
312 .muslsf => "muslsf",
313 .muslx32 => "muslx32",
314 .msvc => "msvc",
315 .itanium => "itanium",
316 .simulator => "simulator",
317 .ohos, .ohoseabi => "ohos",
318 .call0 => "unknown",
319 };
320 try llvm_triple.appendSlice(llvm_abi);
321
322 switch (target.os.versionRange()) {
323 .none,
324 .semver,
325 .windows,
326 => {},
327 inline .hurd, .linux => |ver| if (target.abi.isGnu()) {
328 try llvm_triple.print("{d}.{d}.{d}", .{
329 ver.glibc.major,
330 ver.glibc.minor,
331 ver.glibc.patch,
332 });
333 } else if (@TypeOf(ver) == std.Target.Os.LinuxVersionRange and target.abi.isAndroid()) {
334 try llvm_triple.print("{d}", .{ver.android});
335 },
336 }
337
338 return llvm_triple.toOwnedSlice();
339}
340
34149pub fn supportsTailCall(target: *const std.Target) bool {
34250 return switch (target.cpu.arch) {
34351 .wasm32, .wasm64 => target.cpu.has(.wasm, .tail_call),
......@@ -456,14 +164,12 @@ pub const Object = struct {
456164 const comp = zcu.comp;
457165 const gpa = comp.gpa;
458166 const target = zcu.getTarget();
459 const llvm_target_triple = try targetTriple(arena, target);
460167
461168 var builder = try Builder.init(.{
462169 .allocator = gpa,
463170 .strip = comp.config.debug_format == .strip,
464171 .name = comp.root_name,
465172 .target = target,
466 .triple = llvm_target_triple,
467173 });
468174 errdefer builder.deinit();
469175
src/target.zig+8-3
......@@ -303,9 +303,14 @@ pub fn selfHostedBackendIsAsRobustAsLlvm(target: *const std.Target) bool {
303303 // https://github.com/ziglang/zig/issues/25699
304304 return false;
305305 }
306 if (target.os.tag.isBSD()) {
307 // Self-hosted linker needs work: https://github.com/ziglang/zig/issues/24341
308 return false;
306 // Self-hosted linker needs work: https://github.com/ziglang/zig/issues/24341
307 switch (target.os.tag) {
308 .dragonfly,
309 .freebsd,
310 .netbsd,
311 .openbsd,
312 => return false,
313 else => {},
309314 }
310315 return switch (target.ofmt) {
311316 .elf, .macho => true,
test/tests.zig+9-1
......@@ -3041,7 +3041,15 @@ pub fn wouldUseLlvm(use_llvm: ?bool, query: std.Target.Query, optimize_mode: Opt
30413041 switch (cpu_arch) {
30423042 .x86_64 => {
30433043 if (std.Target.ptrBitWidth_arch_abi(cpu_arch, query.abi orelse .none) != 64) return true;
3044 if (os_tag.isBSD() or os_tag == .illumos) return true;
3044 if (os_tag == .illumos) return true;
3045 switch (os_tag) {
3046 .dragonfly,
3047 .freebsd,
3048 .netbsd,
3049 .openbsd,
3050 => return true,
3051 else => {},
3052 }
30453053 return switch (ofmt) {
30463054 .elf, .macho => return false,
30473055 else => return true,