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 {...@@ -523,7 +523,10 @@ pub fn systemCompiler(target: *const Target) LangOpts.Compiler {
523 // the rest for documentation as fn returns .clang523 // the rest for documentation as fn returns .clang
524 if (target.os.tag.isDarwin() or524 if (target.os.tag.isDarwin() or
525 target.abi.isAndroid() or525 target.abi.isAndroid() or
526 target.os.tag.isBSD() or526 target.os.tag == .dragonfly or
527 target.os.tag == .freebsd or
528 target.os.tag == .netbsd or
529 target.os.tag == .openbsd or
527 target.os.tag == .fuchsia or530 target.os.tag == .fuchsia or
528 target.os.tag == .illumos or531 target.os.tag == .illumos or
529 target.os.tag == .haiku or532 target.os.tag == .haiku or
lib/std/Target.zig+52-14
...@@ -89,6 +89,7 @@ pub const Os = struct {...@@ -89,6 +89,7 @@ pub const Os = struct {
89 };89 };
90 }90 }
9191
92 /// Deprecated; to be removed in 0.18.0. Check for relevant tags instead.
92 pub inline fn isBSD(tag: Tag) bool {93 pub inline fn isBSD(tag: Tag) bool {
93 return tag.isDarwin() or switch (tag) {94 return tag.isDarwin() or switch (tag) {
94 .freebsd, .openbsd, .netbsd, .dragonfly => true,95 .freebsd, .openbsd, .netbsd, .dragonfly => true,
...@@ -1109,7 +1110,7 @@ pub fn toElfMachine(target: *const Target) std.elf.EM {...@@ -1109,7 +1110,7 @@ pub fn toElfMachine(target: *const Target) std.elf.EM {
1109 .riscv32, .riscv32be, .riscv64, .riscv64be => .RISCV,1110 .riscv32, .riscv32be, .riscv64, .riscv64be => .RISCV,
1110 .s390x => .S390,1111 .s390x => .S390,
1111 .sh, .sheb => .SH,1112 .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,
1113 .sparc64 => .SPARCV9,1114 .sparc64 => .SPARCV9,
1114 .ve => .VE,1115 .ve => .VE,
1115 .x86_16, .x86 => .@"386",1116 .x86_16, .x86 => .@"386",
...@@ -1509,7 +1510,10 @@ pub const Cpu = struct {...@@ -1509,7 +1510,10 @@ pub const Cpu = struct {
1509 };1510 };
1510 }1511 }
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 {
1513 return switch (arch) {1517 return switch (arch) {
1514 .aarch64, .aarch64_be => true,1518 .aarch64, .aarch64_be => true,
1515 else => false,1519 else => false,
...@@ -1537,14 +1541,20 @@ pub const Cpu = struct {...@@ -1537,14 +1541,20 @@ pub const Cpu = struct {
1537 };1541 };
1538 }1542 }
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 {
1541 return switch (arch) {1548 return switch (arch) {
1542 .loongarch32, .loongarch64 => true,1549 .loongarch32, .loongarch64 => true,
1543 else => false,1550 else => false,
1544 };1551 };
1545 }1552 }
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 {
1548 return arch.isRiscv32() or arch.isRiscv64();1558 return arch.isRiscv32() or arch.isRiscv64();
1549 }1559 }
15501560
...@@ -1569,50 +1579,74 @@ pub const Cpu = struct {...@@ -1569,50 +1579,74 @@ pub const Cpu = struct {
1569 };1579 };
1570 }1580 }
15711581
1572 pub inline fn isMIPS(arch: Arch) bool {1582 /// Deprecated; to be removed in 0.18.0. Use `isMips` instead.
1573 return arch.isMIPS32() or arch.isMIPS64();1583 pub const isMIPS = isMips;
1584
1585 pub inline fn isMips(arch: Arch) bool {
1586 return arch.isMips32() or arch.isMips64();
1574 }1587 }
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 {
1577 return switch (arch) {1593 return switch (arch) {
1578 .mips, .mipsel => true,1594 .mips, .mipsel => true,
1579 else => false,1595 else => false,
1580 };1596 };
1581 }1597 }
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 {
1584 return switch (arch) {1603 return switch (arch) {
1585 .mips64, .mips64el => true,1604 .mips64, .mips64el => true,
1586 else => false,1605 else => false,
1587 };1606 };
1588 }1607 }
15891608
1590 pub inline fn isPowerPC(arch: Arch) bool {1609 /// Deprecated; to be removed in 0.18.0. Use `isPowerpc` instead.
1591 return arch.isPowerPC32() or arch.isPowerPC64();1610 pub const isPowerPC = isPowerpc;
1611
1612 pub inline fn isPowerpc(arch: Arch) bool {
1613 return arch.isPowerpc32() or arch.isPowerpc64();
1592 }1614 }
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 {
1595 return switch (arch) {1620 return switch (arch) {
1596 .powerpc, .powerpcle => true,1621 .powerpc, .powerpcle => true,
1597 else => false,1622 else => false,
1598 };1623 };
1599 }1624 }
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 {
1602 return switch (arch) {1630 return switch (arch) {
1603 .powerpc64, .powerpc64le => true,1631 .powerpc64, .powerpc64le => true,
1604 else => false,1632 else => false,
1605 };1633 };
1606 }1634 }
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 {
1609 return switch (arch) {1640 return switch (arch) {
1610 .sparc, .sparc64 => true,1641 .sparc, .sparc64 => true,
1611 else => false,1642 else => false,
1612 };1643 };
1613 }1644 }
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 {
1616 return switch (arch) {1650 return switch (arch) {
1617 .spirv32, .spirv64 => true,1651 .spirv32, .spirv64 => true,
1618 else => false,1652 else => false,
...@@ -2146,18 +2180,22 @@ pub fn zigTriple(target: *const Target, allocator: Allocator) Allocator.Error![]...@@ -2146,18 +2180,22 @@ pub fn zigTriple(target: *const Target, allocator: Allocator) Allocator.Error![]
2146 return Query.fromTarget(target).zigTriple(allocator);2180 return Query.fromTarget(target).zigTriple(allocator);
2147}2181}
21482182
2183/// Deprecated; to be removed in 0.18.0. Use `std.zig.target.hurdTupleSimple` instead.
2149pub fn hurdTupleSimple(allocator: Allocator, arch: Cpu.Arch, abi: Abi) ![]u8 {2184pub fn hurdTupleSimple(allocator: Allocator, arch: Cpu.Arch, abi: Abi) ![]u8 {
2150 return std.fmt.allocPrint(allocator, "{s}-{s}", .{ @tagName(arch), @tagName(abi) });2185 return std.fmt.allocPrint(allocator, "{s}-{s}", .{ @tagName(arch), @tagName(abi) });
2151}2186}
21522187
2188/// Deprecated; to be removed in 0.18.0. Use `std.zig.target.hurdTuple` instead.
2153pub fn hurdTuple(target: *const Target, allocator: Allocator) ![]u8 {2189pub fn hurdTuple(target: *const Target, allocator: Allocator) ![]u8 {
2154 return hurdTupleSimple(allocator, target.cpu.arch, target.abi);2190 return hurdTupleSimple(allocator, target.cpu.arch, target.abi);
2155}2191}
21562192
2193/// Deprecated; to be removed in 0.18.0. Use `std.zig.target.linuxTripleSimple` instead.
2157pub fn linuxTripleSimple(allocator: Allocator, arch: Cpu.Arch, os_tag: Os.Tag, abi: Abi) ![]u8 {2194pub fn linuxTripleSimple(allocator: Allocator, arch: Cpu.Arch, os_tag: Os.Tag, abi: Abi) ![]u8 {
2158 return std.fmt.allocPrint(allocator, "{s}-{s}-{s}", .{ @tagName(arch), @tagName(os_tag), @tagName(abi) });2195 return std.fmt.allocPrint(allocator, "{s}-{s}-{s}", .{ @tagName(arch), @tagName(os_tag), @tagName(abi) });
2159}2196}
21602197
2198/// Deprecated; to be removed in 0.18.0. Use `std.zig.target.linuxTriple` instead.
2161pub fn linuxTriple(target: *const Target, allocator: Allocator) ![]u8 {2199pub fn linuxTriple(target: *const Target, allocator: Allocator) ![]u8 {
2162 return linuxTripleSimple(allocator, target.cpu.arch, target.os.tag, target.abi);2200 return linuxTripleSimple(allocator, target.cpu.arch, target.os.tag, target.abi);
2163}2201}
lib/std/zig/llvm/Builder.zig+295-3
...@@ -84,9 +84,300 @@ pub const Options = struct {...@@ -84,9 +84,300 @@ pub const Options = struct {
84 strip: bool = true,84 strip: bool = true,
85 name: []const u8 = &.{},85 name: []const u8 = &.{},
86 target: *const std.Target = &builtin.target,86 target: *const std.Target = &builtin.target,
87 triple: []const u8 = &.{},
88};87};
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
90pub const DataLayout = struct {381pub const DataLayout = struct {
91 endian: ?std.lang.Endian,382 endian: ?std.lang.Endian,
92 int_specs: PrimitiveSpec.Map,383 int_specs: PrimitiveSpec.Map,
...@@ -9610,6 +9901,9 @@ pub fn init(options: Options) Allocator.Error!Builder {...@@ -9610,6 +9901,9 @@ pub fn init(options: Options) Allocator.Error!Builder {
9610 try self.string_indices.append(self.gpa, 0);9901 try self.string_indices.append(self.gpa, 0);
9611 assert(try self.string("") == .empty);9902 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);
9613 self.data_layout = try .parseString(try self.string(DataLayout.stringForTarget(options.target)), &self);9907 self.data_layout = try .parseString(try self.string(DataLayout.stringForTarget(options.target)), &self);
96149908
9615 try self.strtab_string_indices.append(self.gpa, 0);9909 try self.strtab_string_indices.append(self.gpa, 0);
...@@ -9617,8 +9911,6 @@ pub fn init(options: Options) Allocator.Error!Builder {...@@ -9617,8 +9911,6 @@ pub fn init(options: Options) Allocator.Error!Builder {
96179911
9618 if (options.name.len > 0) self.source_filename = try self.string(options.name);9912 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
9622 {9914 {
9623 const static_len = @typeInfo(Type).@"enum".field_names.len - 1;9915 const static_len = @typeInfo(Type).@"enum".field_names.len - 1;
9624 try self.type_map.ensureTotalCapacity(self.gpa, static_len);9916 try self.type_map.ensureTotalCapacity(self.gpa, static_len);
lib/std/zig/system/NativePaths.zig+1-1
...@@ -149,7 +149,7 @@ pub fn detect(...@@ -149,7 +149,7 @@ pub fn detect(
149 }149 }
150150
151 if (builtin.os.tag != .windows and builtin.os.tag != .wasi) {151 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
154 const qual = native_target.ptrBitWidth();154 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 {...@@ -143,6 +143,31 @@ pub fn canBuildLibC(target: *const std.Target) bool {
143 return false;143 return false;
144}144}
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
146/// Returns the subdirectory triple to be used to find the correct glibc for the given `arch`, `os`,171/// Returns the subdirectory triple to be used to find the correct glibc for the given `arch`, `os`,
147/// and `abi` in an installation directory created by glibc's `build-many-glibcs.py` script.172/// and `abi` in an installation directory created by glibc's `build-many-glibcs.py` script.
148///173///
...@@ -162,8 +187,8 @@ pub fn glibcRuntimeTriple(...@@ -162,8 +187,8 @@ pub fn glibcRuntimeTriple(
162 }187 }
163188
164 return switch (os) {189 return switch (os) {
165 .hurd => std.Target.hurdTupleSimple(allocator, arch, abi),190 .hurd => hurdTupleSimple(allocator, arch, abi),
166 .linux => std.Target.linuxTripleSimple(allocator, arch, os, abi),191 .linux => linuxTripleSimple(allocator, arch, os, abi),
167 else => unreachable,192 else => unreachable,
168 };193 };
169}194}
...@@ -179,7 +204,7 @@ pub fn muslRuntimeTriple(...@@ -179,7 +204,7 @@ pub fn muslRuntimeTriple(
179) Allocator.Error![]const u8 {204) Allocator.Error![]const u8 {
180 assert(abi.isMusl());205 assert(abi.isMusl());
181206
182 return std.Target.linuxTripleSimple(allocator, arch, .linux, abi);207 return linuxTripleSimple(allocator, arch, .linux, abi);
183}208}
184209
185pub fn osArchName(target: *const std.Target) [:0]const u8 {210pub fn osArchName(target: *const std.Target) [:0]const u8 {
src/Compilation.zig+1-1
...@@ -6574,7 +6574,7 @@ pub fn addCCArgs(...@@ -6574,7 +6574,7 @@ pub fn addCCArgs(
6574 try argv.append("-integrated-as");6574 try argv.append("-integrated-as");
6575 }6575 }
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);
6578 try argv.appendSlice(&[_][]const u8{ "-target", llvm_triple });6578 try argv.appendSlice(&[_][]const u8{ "-target", llvm_triple });
65796579
6580 if (target.cpu.arch.isThumb()) {6580 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...@@ -46,298 +46,6 @@ pub fn legalizeFeatures(target: *const std.Target) ?*const Air.Legalize.Features
46 };46 };
47}47}
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
341pub fn supportsTailCall(target: *const std.Target) bool {49pub fn supportsTailCall(target: *const std.Target) bool {
342 return switch (target.cpu.arch) {50 return switch (target.cpu.arch) {
343 .wasm32, .wasm64 => target.cpu.has(.wasm, .tail_call),51 .wasm32, .wasm64 => target.cpu.has(.wasm, .tail_call),
...@@ -456,14 +164,12 @@ pub const Object = struct {...@@ -456,14 +164,12 @@ pub const Object = struct {
456 const comp = zcu.comp;164 const comp = zcu.comp;
457 const gpa = comp.gpa;165 const gpa = comp.gpa;
458 const target = zcu.getTarget();166 const target = zcu.getTarget();
459 const llvm_target_triple = try targetTriple(arena, target);
460167
461 var builder = try Builder.init(.{168 var builder = try Builder.init(.{
462 .allocator = gpa,169 .allocator = gpa,
463 .strip = comp.config.debug_format == .strip,170 .strip = comp.config.debug_format == .strip,
464 .name = comp.root_name,171 .name = comp.root_name,
465 .target = target,172 .target = target,
466 .triple = llvm_target_triple,
467 });173 });
468 errdefer builder.deinit();174 errdefer builder.deinit();
469175
src/target.zig+8-3
...@@ -303,9 +303,14 @@ pub fn selfHostedBackendIsAsRobustAsLlvm(target: *const std.Target) bool {...@@ -303,9 +303,14 @@ pub fn selfHostedBackendIsAsRobustAsLlvm(target: *const std.Target) bool {
303 // https://github.com/ziglang/zig/issues/25699303 // https://github.com/ziglang/zig/issues/25699
304 return false;304 return false;
305 }305 }
306 if (target.os.tag.isBSD()) {306 // Self-hosted linker needs work: https://github.com/ziglang/zig/issues/24341
307 // Self-hosted linker needs work: https://github.com/ziglang/zig/issues/24341307 switch (target.os.tag) {
308 return false;308 .dragonfly,
309 .freebsd,
310 .netbsd,
311 .openbsd,
312 => return false,
313 else => {},
309 }314 }
310 return switch (target.ofmt) {315 return switch (target.ofmt) {
311 .elf, .macho => true,316 .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...@@ -3041,7 +3041,15 @@ pub fn wouldUseLlvm(use_llvm: ?bool, query: std.Target.Query, optimize_mode: Opt
3041 switch (cpu_arch) {3041 switch (cpu_arch) {
3042 .x86_64 => {3042 .x86_64 => {
3043 if (std.Target.ptrBitWidth_arch_abi(cpu_arch, query.abi orelse .none) != 64) return true;3043 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 }
3045 return switch (ofmt) {3053 return switch (ofmt) {
3046 .elf, .macho => return false,3054 .elf, .macho => return false,
3047 else => return true,3055 else => return true,