authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-04-14 15:24:01-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-04-14 15:33:46-04:00
log533f54c68ee18a910e348bf273a713842fdfd127
tree9294d5b3cf05181aa6479c5bc7d286c5b97a90e0
parente45bdc6bd6e47ec3f7a06dbb48f24e842bf43a0d

Target: cleanup


4 files changed, 510 insertions(+), 588 deletions(-)

lib/std/Target.zig+450-422
......@@ -81,14 +81,48 @@ pub const Os = struct {
8181 return tag == .solaris or tag == .illumos;
8282 }
8383
84 pub fn exeFileExt(tag: Tag, arch: Cpu.Arch) [:0]const u8 {
85 return switch (tag) {
86 .windows => ".exe",
87 .uefi => ".efi",
88 .plan9 => arch.plan9Ext(),
89 else => switch (arch) {
90 .wasm32, .wasm64 => ".wasm",
91 else => "",
92 },
93 };
94 }
95
96 pub fn staticLibSuffix(tag: Tag, abi: Abi) [:0]const u8 {
97 return switch (abi) {
98 .msvc => ".lib",
99 else => switch (tag) {
100 .windows, .uefi => ".lib",
101 else => ".a",
102 },
103 };
104 }
105
84106 pub fn dynamicLibSuffix(tag: Tag) [:0]const u8 {
85 if (tag.isDarwin()) {
86 return ".dylib";
87 }
88 switch (tag) {
89 .windows => return ".dll",
90 else => return ".so",
91 }
107 return switch (tag) {
108 .windows, .uefi => ".dll",
109 .ios, .macos, .watchos, .tvos => ".dylib",
110 else => ".so",
111 };
112 }
113
114 pub fn libPrefix(tag: Os.Tag, abi: Abi) [:0]const u8 {
115 return switch (abi) {
116 .msvc => "",
117 else => switch (tag) {
118 .windows, .uefi => "",
119 else => "lib",
120 },
121 };
122 }
123
124 pub inline fn isGnuLibC(tag: Os.Tag, abi: Abi) bool {
125 return tag == .linux and abi.isGnu();
92126 }
93127
94128 pub fn defaultVersionRange(tag: Tag, arch: Cpu.Arch) Os {
......@@ -97,6 +131,78 @@ pub const Os = struct {
97131 .version_range = VersionRange.default(tag, arch),
98132 };
99133 }
134
135 pub inline fn getVersionRangeTag(tag: Tag) @typeInfo(TaggedVersionRange).Union.tag_type.? {
136 return switch (tag) {
137 .freestanding,
138 .ananas,
139 .cloudabi,
140 .fuchsia,
141 .kfreebsd,
142 .lv2,
143 .zos,
144 .haiku,
145 .minix,
146 .rtems,
147 .nacl,
148 .aix,
149 .cuda,
150 .nvcl,
151 .amdhsa,
152 .ps4,
153 .ps5,
154 .elfiamcu,
155 .mesa3d,
156 .contiki,
157 .amdpal,
158 .hermit,
159 .hurd,
160 .wasi,
161 .emscripten,
162 .driverkit,
163 .shadermodel,
164 .liteos,
165 .uefi,
166 .opencl, // TODO: OpenCL versions
167 .glsl450, // TODO: GLSL versions
168 .vulkan,
169 .plan9,
170 .illumos,
171 .other,
172 => .none,
173
174 .freebsd,
175 .macos,
176 .ios,
177 .tvos,
178 .watchos,
179 .netbsd,
180 .openbsd,
181 .dragonfly,
182 .solaris,
183 => .semver,
184
185 .linux => .linux,
186
187 .windows => .windows,
188 };
189 }
190
191 pub fn archName(tag: Tag, arch: Cpu.Arch) [:0]const u8 {
192 return switch (tag) {
193 .linux => switch (arch) {
194 .arm, .armeb, .thumb, .thumbeb => "arm",
195 .aarch64, .aarch64_be, .aarch64_32 => "aarch64",
196 .mips, .mipsel, .mips64, .mips64el => "mips",
197 .powerpc, .powerpcle, .powerpc64, .powerpc64le => "powerpc",
198 .riscv32, .riscv64 => "riscv",
199 .sparc, .sparcel, .sparc64 => "sparc",
200 .x86, .x86_64 => "x86",
201 else => @tagName(arch),
202 },
203 else => @tagName(arch),
204 };
205 }
100206 };
101207
102208 /// Based on NTDDI version constants from
......@@ -142,52 +248,60 @@ pub const Os = struct {
142248 19042, //win10_fe aka win10_20h2
143249 };
144250
145 /// Returns whether the first version `self` is newer (greater) than or equal to the second version `ver`.
146 pub inline fn isAtLeast(self: WindowsVersion, ver: WindowsVersion) bool {
147 return @intFromEnum(self) >= @intFromEnum(ver);
251 /// Returns whether the first version `ver` is newer (greater) than or equal to the second version `ver`.
252 pub inline fn isAtLeast(ver: WindowsVersion, min_ver: WindowsVersion) bool {
253 return @intFromEnum(ver) >= @intFromEnum(min_ver);
148254 }
149255
150256 pub const Range = struct {
151257 min: WindowsVersion,
152258 max: WindowsVersion,
153259
154 pub inline fn includesVersion(self: Range, ver: WindowsVersion) bool {
155 return @intFromEnum(ver) >= @intFromEnum(self.min) and @intFromEnum(ver) <= @intFromEnum(self.max);
260 pub inline fn includesVersion(range: Range, ver: WindowsVersion) bool {
261 return @intFromEnum(ver) >= @intFromEnum(range.min) and
262 @intFromEnum(ver) <= @intFromEnum(range.max);
156263 }
157264
158265 /// Checks if system is guaranteed to be at least `version` or older than `version`.
159266 /// Returns `null` if a runtime check is required.
160 pub inline fn isAtLeast(self: Range, ver: WindowsVersion) ?bool {
161 if (@intFromEnum(self.min) >= @intFromEnum(ver)) return true;
162 if (@intFromEnum(self.max) < @intFromEnum(ver)) return false;
267 pub inline fn isAtLeast(range: Range, min_ver: WindowsVersion) ?bool {
268 if (@intFromEnum(range.min) >= @intFromEnum(min_ver)) return true;
269 if (@intFromEnum(range.max) < @intFromEnum(min_ver)) return false;
163270 return null;
164271 }
165272 };
166273
274 pub fn parse(str: []const u8) !WindowsVersion {
275 return std.meta.stringToEnum(WindowsVersion, str) orelse
276 @enumFromInt(std.fmt.parseInt(u32, str, 0) catch
277 return error.InvalidOperatingSystemVersion);
278 }
279
167280 /// This function is defined to serialize a Zig source code representation of this
168281 /// type, that, when parsed, will deserialize into the same data.
169282 pub fn format(
170 self: WindowsVersion,
171 comptime fmt: []const u8,
283 ver: WindowsVersion,
284 comptime fmt_str: []const u8,
172285 _: std.fmt.FormatOptions,
173 out_stream: anytype,
174 ) !void {
175 if (comptime std.mem.eql(u8, fmt, "s")) {
176 if (@intFromEnum(self) >= @intFromEnum(WindowsVersion.nt4) and @intFromEnum(self) <= @intFromEnum(WindowsVersion.latest)) {
177 try std.fmt.format(out_stream, ".{s}", .{@tagName(self)});
178 } else {
179 // TODO this code path breaks zig triples, but it is used in `builtin`
180 try std.fmt.format(out_stream, "@enumFromInt(Target.Os.WindowsVersion, 0x{X:0>8})", .{@intFromEnum(self)});
181 }
182 } else if (fmt.len == 0) {
183 if (@intFromEnum(self) >= @intFromEnum(WindowsVersion.nt4) and @intFromEnum(self) <= @intFromEnum(WindowsVersion.latest)) {
184 try std.fmt.format(out_stream, "WindowsVersion.{s}", .{@tagName(self)});
185 } else {
186 try std.fmt.format(out_stream, "WindowsVersion(0x{X:0>8})", .{@intFromEnum(self)});
187 }
188 } else {
189 std.fmt.invalidFmtError(fmt, self);
190 }
286 writer: anytype,
287 ) @TypeOf(writer).Error!void {
288 const maybe_name = std.enums.tagName(WindowsVersion, ver);
289 if (comptime std.mem.eql(u8, fmt_str, "s")) {
290 if (maybe_name) |name|
291 try writer.print(".{s}", .{name})
292 else
293 try writer.print(".{d}", .{@intFromEnum(ver)});
294 } else if (comptime std.mem.eql(u8, fmt_str, "c")) {
295 if (maybe_name) |name|
296 try writer.print(".{s}", .{name})
297 else
298 try writer.print("@enumFromInt(0x{X:0>8})", .{@intFromEnum(ver)});
299 } else if (fmt_str.len == 0) {
300 if (maybe_name) |name|
301 try writer.print("WindowsVersion.{s}", .{name})
302 else
303 try writer.print("WindowsVersion(0x{X:0>8})", .{@intFromEnum(ver)});
304 } else std.fmt.invalidFmtError(fmt_str, ver);
191305 }
192306 };
193307
......@@ -195,14 +309,14 @@ pub const Os = struct {
195309 range: std.SemanticVersion.Range,
196310 glibc: std.SemanticVersion,
197311
198 pub inline fn includesVersion(self: LinuxVersionRange, ver: std.SemanticVersion) bool {
199 return self.range.includesVersion(ver);
312 pub inline fn includesVersion(range: LinuxVersionRange, ver: std.SemanticVersion) bool {
313 return range.range.includesVersion(ver);
200314 }
201315
202316 /// Checks if system is guaranteed to be at least `version` or older than `version`.
203317 /// Returns `null` if a runtime check is required.
204 pub inline fn isAtLeast(self: LinuxVersionRange, ver: std.SemanticVersion) ?bool {
205 return self.range.isAtLeast(ver);
318 pub inline fn isAtLeast(range: LinuxVersionRange, ver: std.SemanticVersion) ?bool {
319 return range.range.isAtLeast(ver);
206320 }
207321 };
208322
......@@ -239,7 +353,7 @@ pub const Os = struct {
239353 /// The default `VersionRange` represents the range that the Zig Standard Library
240354 /// bases its abstractions on.
241355 pub fn default(tag: Tag, arch: Cpu.Arch) VersionRange {
242 switch (tag) {
356 return switch (tag) {
243357 .freestanding,
244358 .ananas,
245359 .cloudabi,
......@@ -275,15 +389,15 @@ pub const Os = struct {
275389 .plan9,
276390 .illumos,
277391 .other,
278 => return .{ .none = {} },
392 => .{ .none = {} },
279393
280 .freebsd => return .{
394 .freebsd => .{
281395 .semver = std.SemanticVersion.Range{
282396 .min = .{ .major = 12, .minor = 0, .patch = 0 },
283397 .max = .{ .major = 14, .minor = 0, .patch = 0 },
284398 },
285399 },
286 .macos => return switch (arch) {
400 .macos => switch (arch) {
287401 .aarch64 => VersionRange{
288402 .semver = .{
289403 .min = .{ .major = 11, .minor = 7, .patch = 1 },
......@@ -298,50 +412,50 @@ pub const Os = struct {
298412 },
299413 else => unreachable,
300414 },
301 .ios => return .{
415 .ios => .{
302416 .semver = .{
303417 .min = .{ .major = 12, .minor = 0, .patch = 0 },
304418 .max = .{ .major = 17, .minor = 1, .patch = 0 },
305419 },
306420 },
307 .watchos => return .{
421 .watchos => .{
308422 .semver = .{
309423 .min = .{ .major = 6, .minor = 0, .patch = 0 },
310424 .max = .{ .major = 10, .minor = 1, .patch = 0 },
311425 },
312426 },
313 .tvos => return .{
427 .tvos => .{
314428 .semver = .{
315429 .min = .{ .major = 13, .minor = 0, .patch = 0 },
316430 .max = .{ .major = 17, .minor = 1, .patch = 0 },
317431 },
318432 },
319 .netbsd => return .{
433 .netbsd => .{
320434 .semver = .{
321435 .min = .{ .major = 8, .minor = 0, .patch = 0 },
322436 .max = .{ .major = 10, .minor = 0, .patch = 0 },
323437 },
324438 },
325 .openbsd => return .{
439 .openbsd => .{
326440 .semver = .{
327441 .min = .{ .major = 6, .minor = 8, .patch = 0 },
328442 .max = .{ .major = 7, .minor = 4, .patch = 0 },
329443 },
330444 },
331 .dragonfly => return .{
445 .dragonfly => .{
332446 .semver = .{
333447 .min = .{ .major = 5, .minor = 8, .patch = 0 },
334448 .max = .{ .major = 6, .minor = 4, .patch = 0 },
335449 },
336450 },
337 .solaris => return .{
451 .solaris => .{
338452 .semver = .{
339453 .min = .{ .major = 5, .minor = 11, .patch = 0 },
340454 .max = .{ .major = 5, .minor = 11, .patch = 0 },
341455 },
342456 },
343457
344 .linux => return .{
458 .linux => .{
345459 .linux = .{
346460 .range = .{
347461 .min = .{ .major = 4, .minor = 19, .patch = 0 },
......@@ -351,13 +465,13 @@ pub const Os = struct {
351465 },
352466 },
353467
354 .windows => return .{
468 .windows => .{
355469 .windows = .{
356470 .min = .win8_1,
357471 .max = WindowsVersion.latest,
358472 },
359473 },
360 }
474 };
361475 }
362476 };
363477
......@@ -370,38 +484,28 @@ pub const Os = struct {
370484
371485 /// Provides a tagged union. `Target` does not store the tag because it is
372486 /// redundant with the OS tag; this function abstracts that part away.
373 pub inline fn getVersionRange(self: Os) TaggedVersionRange {
374 switch (self.tag) {
375 .linux => return TaggedVersionRange{ .linux = self.version_range.linux },
376 .windows => return TaggedVersionRange{ .windows = self.version_range.windows },
377
378 .freebsd,
379 .macos,
380 .ios,
381 .tvos,
382 .watchos,
383 .netbsd,
384 .openbsd,
385 .dragonfly,
386 .solaris,
387 => return TaggedVersionRange{ .semver = self.version_range.semver },
388
389 else => return .none,
390 }
487 pub inline fn getVersionRange(os: Os) TaggedVersionRange {
488 return switch (os.tag.getVersionRangeTag()) {
489 .none => .{ .none = {} },
490 .semver => .{ .semver = os.version_range.semver },
491 .linux => .{ .linux = os.version_range.linux },
492 .windows => .{ .windows = os.version_range.windows },
493 };
391494 }
392495
393496 /// Checks if system is guaranteed to be at least `version` or older than `version`.
394497 /// Returns `null` if a runtime check is required.
395 pub inline fn isAtLeast(self: Os, comptime tag: Tag, version: switch (tag) {
396 else => std.SemanticVersion,
498 pub inline fn isAtLeast(os: Os, comptime tag: Tag, ver: switch (tag.getVersionRangeTag()) {
499 .none => void,
500 .semver, .linux => std.SemanticVersion,
397501 .windows => WindowsVersion,
398502 }) ?bool {
399 if (self.tag != tag) return false;
400
401 return switch (tag) {
402 .linux => self.version_range.linux.isAtLeast(version),
403 .windows => self.version_range.windows.isAtLeast(version),
404 else => self.version_range.semver.isAtLeast(version),
503 return if (os.tag != tag) false else switch (tag.getVersionRangeTag()) {
504 .none => true,
505 inline .semver,
506 .linux,
507 .windows,
508 => |field| @field(os.version_range, @tagName(field)).isAtLeast(ver),
405509 };
406510 }
407511
......@@ -528,11 +632,8 @@ pub const Abi = enum {
528632 mesh,
529633 amplification,
530634
531 pub fn default(arch: Cpu.Arch, target_os: Os) Abi {
532 if (arch.isWasm()) {
533 return .musl;
534 }
535 switch (target_os.tag) {
635 pub fn default(arch: Cpu.Arch, os: Os) Abi {
636 return if (arch.isWasm()) .musl else switch (os.tag) {
536637 .freestanding,
537638 .ananas,
538639 .cloudabi,
......@@ -554,7 +655,7 @@ pub const Abi = enum {
554655 .amdpal,
555656 .hermit,
556657 .other,
557 => return .eabi,
658 => .eabi,
558659 .openbsd,
559660 .freebsd,
560661 .fuchsia,
......@@ -563,12 +664,12 @@ pub const Abi = enum {
563664 .hurd,
564665 .haiku,
565666 .windows,
566 => return .gnu,
567 .uefi => return .msvc,
667 => .gnu,
668 .uefi => .msvc,
568669 .linux,
569670 .wasi,
570671 .emscripten,
571 => return .musl,
672 => .musl,
572673 .opencl, // TODO: SPIR-V ABIs with Linkage capability
573674 .glsl450,
574675 .vulkan,
......@@ -582,8 +683,8 @@ pub const Abi = enum {
582683 .liteos, // TODO: audit this
583684 .solaris,
584685 .illumos,
585 => return .none,
586 }
686 => .none,
687 };
587688 }
588689
589690 pub inline fn isGnu(abi: Abi) bool {
......@@ -635,7 +736,7 @@ pub const ObjectFormat = enum {
635736 /// Nvidia PTX format
636737 nvptx,
637738
638 pub fn fileExt(of: ObjectFormat, cpu_arch: Cpu.Arch) [:0]const u8 {
739 pub fn fileExt(of: ObjectFormat, arch: Cpu.Arch) [:0]const u8 {
639740 return switch (of) {
640741 .coff => ".obj",
641742 .elf, .macho, .wasm => ".o",
......@@ -643,18 +744,18 @@ pub const ObjectFormat = enum {
643744 .spirv => ".spv",
644745 .hex => ".ihex",
645746 .raw => ".bin",
646 .plan9 => plan9Ext(cpu_arch),
747 .plan9 => arch.plan9Ext(),
647748 .nvptx => ".ptx",
648749 .dxcontainer => ".dxil",
649750 };
650751 }
651752
652 pub fn default(os_tag: Os.Tag, cpu_arch: Cpu.Arch) ObjectFormat {
753 pub fn default(os_tag: Os.Tag, arch: Cpu.Arch) ObjectFormat {
653754 return switch (os_tag) {
654755 .windows, .uefi => .coff,
655756 .ios, .macos, .watchos, .tvos => .macho,
656757 .plan9 => .plan9,
657 else => return switch (cpu_arch) {
758 else => switch (arch) {
658759 .wasm32, .wasm64 => .wasm,
659760 .spirv32, .spirv64 => .spirv,
660761 .nvptx, .nvptx64 => .nvptx,
......@@ -725,14 +826,14 @@ pub const Cpu = struct {
725826
726827 pub fn isEnabled(set: Set, arch_feature_index: Index) bool {
727828 const usize_index = arch_feature_index / @bitSizeOf(usize);
728 const bit_index = @as(ShiftInt, @intCast(arch_feature_index % @bitSizeOf(usize)));
829 const bit_index: ShiftInt = @intCast(arch_feature_index % @bitSizeOf(usize));
729830 return (set.ints[usize_index] & (@as(usize, 1) << bit_index)) != 0;
730831 }
731832
732833 /// Adds the specified feature but not its dependencies.
733834 pub fn addFeature(set: *Set, arch_feature_index: Index) void {
734835 const usize_index = arch_feature_index / @bitSizeOf(usize);
735 const bit_index = @as(ShiftInt, @intCast(arch_feature_index % @bitSizeOf(usize)));
836 const bit_index: ShiftInt = @intCast(arch_feature_index % @bitSizeOf(usize));
736837 set.ints[usize_index] |= @as(usize, 1) << bit_index;
737838 }
738839
......@@ -751,7 +852,7 @@ pub const Cpu = struct {
751852 /// Removes the specified feature but not its dependents.
752853 pub fn removeFeature(set: *Set, arch_feature_index: Index) void {
753854 const usize_index = arch_feature_index / @bitSizeOf(usize);
754 const bit_index = @as(ShiftInt, @intCast(arch_feature_index % @bitSizeOf(usize)));
855 const bit_index: ShiftInt = @intCast(arch_feature_index % @bitSizeOf(usize));
755856 set.ints[usize_index] &= ~(@as(usize, 1) << bit_index);
756857 }
757858
......@@ -773,7 +874,7 @@ pub const Cpu = struct {
773874 var old = set.ints;
774875 while (true) {
775876 for (all_features_list, 0..) |feature, index_usize| {
776 const index = @as(Index, @intCast(index_usize));
877 const index: Index = @intCast(index_usize);
777878 if (set.isEnabled(index)) {
778879 set.addFeatureSet(feature.dependencies);
779880 }
......@@ -785,7 +886,7 @@ pub const Cpu = struct {
785886 }
786887
787888 pub fn asBytes(set: *const Set) *const [byte_count]u8 {
788 return @as(*const [byte_count]u8, @ptrCast(&set.ints));
889 return std.mem.sliceAsBytes(&set.ints)[0..byte_count];
789890 }
790891
791892 pub fn eql(set: Set, other_set: Set) bool {
......@@ -1231,7 +1332,7 @@ pub const Cpu = struct {
12311332 }
12321333
12331334 /// Returns a name that matches the lib/std/target/* source file name.
1234 pub fn genericName(arch: Arch) []const u8 {
1335 pub fn genericName(arch: Arch) [:0]const u8 {
12351336 return switch (arch) {
12361337 .arm, .armeb, .thumb, .thumbeb => "arm",
12371338 .aarch64, .aarch64_be, .aarch64_32 => "aarch64",
......@@ -1320,6 +1421,30 @@ pub const Cpu = struct {
13201421 const finalized = array;
13211422 return &finalized;
13221423 }
1424
1425 /// 0c spim little-endian MIPS 3000 family
1426 /// 1c 68000 Motorola MC68000
1427 /// 2c 68020 Motorola MC68020
1428 /// 5c arm little-endian ARM
1429 /// 6c amd64 AMD64 and compatibles (e.g., Intel EM64T)
1430 /// 7c arm64 ARM64 (ARMv8)
1431 /// 8c 386 Intel x86, i486, Pentium, etc.
1432 /// kc sparc Sun SPARC
1433 /// qc power Power PC
1434 /// vc mips big-endian MIPS 3000 family
1435 pub fn plan9Ext(arch: Cpu.Arch) [:0]const u8 {
1436 return switch (arch) {
1437 .arm => ".5",
1438 .x86_64 => ".6",
1439 .aarch64 => ".7",
1440 .x86 => ".8",
1441 .sparc => ".k",
1442 .powerpc, .powerpcle => ".q",
1443 .mips, .mipsel => ".v",
1444 // ISAs without designated characters get 'X' for lack of a better option.
1445 else => ".X",
1446 };
1447 }
13231448 };
13241449
13251450 pub const Model = struct {
......@@ -1399,112 +1524,76 @@ pub const Cpu = struct {
13991524 }
14001525};
14011526
1402pub fn zigTriple(self: Target, allocator: Allocator) Allocator.Error![]u8 {
1403 return Query.fromTarget(self).zigTriple(allocator);
1404}
1405
1406pub fn linuxTripleSimple(allocator: Allocator, cpu_arch: Cpu.Arch, os_tag: Os.Tag, abi: Abi) ![]u8 {
1407 return std.fmt.allocPrint(allocator, "{s}-{s}-{s}", .{ @tagName(cpu_arch), @tagName(os_tag), @tagName(abi) });
1408}
1409
1410pub fn linuxTriple(self: Target, allocator: Allocator) ![]u8 {
1411 return linuxTripleSimple(allocator, self.cpu.arch, self.os.tag, self.abi);
1527pub fn zigTriple(target: Target, allocator: Allocator) Allocator.Error![]u8 {
1528 return Query.fromTarget(target).zigTriple(allocator);
14121529}
14131530
1414pub fn exeFileExtSimple(cpu_arch: Cpu.Arch, os_tag: Os.Tag) [:0]const u8 {
1415 return switch (os_tag) {
1416 .windows => ".exe",
1417 .uefi => ".efi",
1418 .plan9 => plan9Ext(cpu_arch),
1419 else => switch (cpu_arch) {
1420 .wasm32, .wasm64 => ".wasm",
1421 else => "",
1422 },
1423 };
1424}
1425
1426pub fn exeFileExt(self: Target) [:0]const u8 {
1427 return exeFileExtSimple(self.cpu.arch, self.os.tag);
1428}
1429
1430pub fn staticLibSuffix_os_abi(os_tag: Os.Tag, abi: Abi) [:0]const u8 {
1431 if (abi == .msvc) {
1432 return ".lib";
1433 }
1434 switch (os_tag) {
1435 .windows, .uefi => return ".lib",
1436 else => return ".a",
1437 }
1531pub fn linuxTripleSimple(allocator: Allocator, arch: Cpu.Arch, os_tag: Os.Tag, abi: Abi) ![]u8 {
1532 return std.fmt.allocPrint(allocator, "{s}-{s}-{s}", .{ @tagName(arch), @tagName(os_tag), @tagName(abi) });
14381533}
14391534
1440pub fn staticLibSuffix(self: Target) [:0]const u8 {
1441 return staticLibSuffix_os_abi(self.os.tag, self.abi);
1535pub fn linuxTriple(target: Target, allocator: Allocator) ![]u8 {
1536 return linuxTripleSimple(allocator, target.cpu.arch, target.os.tag, target.abi);
14421537}
14431538
1444pub fn dynamicLibSuffix(self: Target) [:0]const u8 {
1445 return self.os.tag.dynamicLibSuffix();
1539pub fn exeFileExt(target: Target) [:0]const u8 {
1540 return target.os.tag.exeFileExt(target.cpu.arch);
14461541}
14471542
1448pub fn libPrefix_os_abi(os_tag: Os.Tag, abi: Abi) [:0]const u8 {
1449 if (abi == .msvc) {
1450 return "";
1451 }
1452 switch (os_tag) {
1453 .windows, .uefi => return "",
1454 else => return "lib",
1455 }
1543pub fn staticLibSuffix(target: Target) [:0]const u8 {
1544 return target.os.tag.staticLibSuffix(target.abi);
14561545}
14571546
1458pub fn libPrefix(self: Target) [:0]const u8 {
1459 return libPrefix_os_abi(self.os.tag, self.abi);
1547pub fn dynamicLibSuffix(target: Target) [:0]const u8 {
1548 return target.os.tag.dynamicLibSuffix();
14601549}
14611550
1462pub inline fn isMinGW(self: Target) bool {
1463 return self.os.tag == .windows and self.isGnu();
1551pub fn libPrefix(target: Target) [:0]const u8 {
1552 return target.os.tag.libPrefix(target.abi);
14641553}
14651554
1466pub inline fn isGnu(self: Target) bool {
1467 return self.abi.isGnu();
1555pub inline fn isMinGW(target: Target) bool {
1556 return target.os.tag == .windows and target.isGnu();
14681557}
14691558
1470pub inline fn isMusl(self: Target) bool {
1471 return self.abi.isMusl();
1559pub inline fn isGnu(target: Target) bool {
1560 return target.abi.isGnu();
14721561}
14731562
1474pub inline fn isAndroid(self: Target) bool {
1475 return self.abi == .android;
1563pub inline fn isMusl(target: Target) bool {
1564 return target.abi.isMusl();
14761565}
14771566
1478pub inline fn isWasm(self: Target) bool {
1479 return self.cpu.arch.isWasm();
1567pub inline fn isAndroid(target: Target) bool {
1568 return target.abi == .android;
14801569}
14811570
1482pub inline fn isDarwin(self: Target) bool {
1483 return self.os.tag.isDarwin();
1571pub inline fn isWasm(target: Target) bool {
1572 return target.cpu.arch.isWasm();
14841573}
14851574
1486pub inline fn isBSD(self: Target) bool {
1487 return self.os.tag.isBSD();
1575pub inline fn isDarwin(target: Target) bool {
1576 return target.os.tag.isDarwin();
14881577}
14891578
1490pub inline fn isBpfFreestanding(self: Target) bool {
1491 return self.cpu.arch.isBpf() and self.os.tag == .freestanding;
1579pub inline fn isBSD(target: Target) bool {
1580 return target.os.tag.isBSD();
14921581}
14931582
1494pub inline fn isGnuLibC_os_tag_abi(os_tag: Os.Tag, abi: Abi) bool {
1495 return os_tag == .linux and abi.isGnu();
1583pub inline fn isBpfFreestanding(target: Target) bool {
1584 return target.cpu.arch.isBpf() and target.os.tag == .freestanding;
14961585}
14971586
1498pub inline fn isGnuLibC(self: Target) bool {
1499 return isGnuLibC_os_tag_abi(self.os.tag, self.abi);
1587pub inline fn isGnuLibC(target: Target) bool {
1588 return target.os.tag.isGnuLibC(target.abi);
15001589}
15011590
1502pub inline fn supportsNewStackCall(self: Target) bool {
1503 return !self.cpu.arch.isWasm();
1591pub inline fn supportsNewStackCall(target: Target) bool {
1592 return !target.cpu.arch.isWasm();
15041593}
15051594
1506pub inline fn isSpirV(self: Target) bool {
1507 return self.cpu.arch.isSpirV();
1595pub inline fn isSpirV(target: Target) bool {
1596 return target.cpu.arch.isSpirV();
15081597}
15091598
15101599pub const FloatAbi = enum {
......@@ -1512,15 +1601,15 @@ pub const FloatAbi = enum {
15121601 soft,
15131602};
15141603
1515pub inline fn getFloatAbi(self: Target) FloatAbi {
1516 return self.abi.floatAbi();
1604pub inline fn getFloatAbi(target: Target) FloatAbi {
1605 return target.abi.floatAbi();
15171606}
15181607
1519pub inline fn hasDynamicLinker(self: Target) bool {
1520 if (self.cpu.arch.isWasm()) {
1608pub inline fn hasDynamicLinker(target: Target) bool {
1609 if (target.cpu.arch.isWasm()) {
15211610 return false;
15221611 }
1523 switch (self.os.tag) {
1612 switch (target.os.tag) {
15241613 .freestanding,
15251614 .ios,
15261615 .tvos,
......@@ -1547,259 +1636,210 @@ pub const DynamicLinker = struct {
15471636
15481637 /// Used to construct the dynamic linker path. This field should not be used
15491638 /// directly. See `get` and `set`.
1550 max_byte: ?u8,
1639 len: u8,
15511640
1552 pub const none: DynamicLinker = .{
1553 .buffer = undefined,
1554 .max_byte = null,
1555 };
1641 pub const none: DynamicLinker = .{ .buffer = undefined, .len = 0 };
15561642
15571643 /// Asserts that the length is less than or equal to 255 bytes.
1558 pub fn init(dl_or_null: ?[]const u8) DynamicLinker {
1559 var result: DynamicLinker = undefined;
1560 result.set(dl_or_null);
1561 return result;
1644 pub fn init(maybe_path: ?[]const u8) DynamicLinker {
1645 var dl: DynamicLinker = undefined;
1646 dl.set(maybe_path);
1647 return dl;
1648 }
1649
1650 pub fn initFmt(comptime fmt_str: []const u8, args: anytype) !DynamicLinker {
1651 var dl: DynamicLinker = undefined;
1652 try dl.setFmt(fmt_str, args);
1653 return dl;
15621654 }
15631655
15641656 /// The returned memory has the same lifetime as the `DynamicLinker`.
1565 pub fn get(self: *const DynamicLinker) ?[]const u8 {
1566 const m: usize = self.max_byte orelse return null;
1567 return self.buffer[0 .. m + 1];
1657 pub fn get(dl: *const DynamicLinker) ?[]const u8 {
1658 return if (dl.len > 0) dl.buffer[0..dl.len] else null;
15681659 }
15691660
15701661 /// Asserts that the length is less than or equal to 255 bytes.
1571 pub fn set(self: *DynamicLinker, dl_or_null: ?[]const u8) void {
1572 if (dl_or_null) |dl| {
1573 @memcpy(self.buffer[0..dl.len], dl);
1574 self.max_byte = @intCast(dl.len - 1);
1575 } else {
1576 self.max_byte = null;
1577 }
1662 pub fn set(dl: *DynamicLinker, maybe_path: ?[]const u8) void {
1663 const path = maybe_path orelse "";
1664 @memcpy(dl.buffer[0..path.len], path);
1665 dl.len = @intCast(path.len);
15781666 }
15791667
1580 pub fn eql(a: DynamicLinker, b: DynamicLinker) bool {
1581 const a_m = a.max_byte orelse return b.max_byte == null;
1582 const b_m = b.max_byte orelse return false;
1583 if (a_m != b_m) return false;
1584 const a_s = a.buffer[0 .. a_m + 1];
1585 const b_s = b.buffer[0 .. a_m + 1];
1586 return std.mem.eql(u8, a_s, b_s);
1668 /// Asserts that the length is less than or equal to 255 bytes.
1669 pub fn setFmt(dl: *DynamicLinker, comptime fmt_str: []const u8, args: anytype) !void {
1670 dl.len = @intCast((try std.fmt.bufPrint(&dl.buffer, fmt_str, args)).len);
15871671 }
1588};
1589
1590pub fn standardDynamicLinkerPath(target: Target) DynamicLinker {
1591 return standardDynamicLinkerPath_cpu_os_abi(target.cpu, target.os.tag, target.abi);
1592}
15931672
1594pub fn standardDynamicLinkerPath_cpu_os_abi(cpu: Cpu, os_tag: Os.Tag, abi: Abi) DynamicLinker {
1595 var result = DynamicLinker.none;
1596 const S = struct {
1597 fn print(r: *DynamicLinker, comptime fmt: []const u8, args: anytype) DynamicLinker {
1598 r.max_byte = @as(u8, @intCast((std.fmt.bufPrint(&r.buffer, fmt, args) catch unreachable).len - 1));
1599 return r.*;
1600 }
1601 fn copy(r: *DynamicLinker, s: []const u8) DynamicLinker {
1602 @memcpy(r.buffer[0..s.len], s);
1603 r.max_byte = @as(u8, @intCast(s.len - 1));
1604 return r.*;
1605 }
1606 };
1607 const print = S.print;
1608 const copy = S.copy;
1609
1610 if (abi == .android) {
1611 const suffix = if (ptrBitWidth_cpu_abi(cpu, abi) == 64) "64" else "";
1612 return print(&result, "/system/bin/linker{s}", .{suffix});
1673 pub fn eql(lhs: DynamicLinker, rhs: DynamicLinker) bool {
1674 return std.mem.eql(u8, lhs.buffer[0..lhs.len], rhs.buffer[0..rhs.len]);
16131675 }
16141676
1615 if (abi.isMusl()) {
1616 const is_arm = switch (cpu.arch) {
1617 .arm, .armeb, .thumb, .thumbeb => true,
1618 else => false,
1619 };
1620 const arch_part = switch (cpu.arch) {
1621 .arm, .thumb => "arm",
1622 .armeb, .thumbeb => "armeb",
1623 else => |arch| @tagName(arch),
1624 };
1625 const arch_suffix = if (is_arm and abi.floatAbi() == .hard) "hf" else "";
1626 return print(&result, "/lib/ld-musl-{s}{s}.so.1", .{ arch_part, arch_suffix });
1627 }
1677 pub fn standard(cpu: Cpu, os_tag: Os.Tag, abi: Abi) DynamicLinker {
1678 return if (abi == .android) initFmt("/system/bin/linker{s}", .{
1679 if (ptrBitWidth_cpu_abi(cpu, abi) == 64) "64" else "",
1680 }) catch unreachable else if (abi.isMusl()) return initFmt("/lib/ld-musl-{s}{s}.so.1", .{
1681 @tagName(switch (cpu.arch) {
1682 .thumb => .arm,
1683 .thumbeb => .armeb,
1684 else => cpu.arch,
1685 }),
1686 if (cpu.arch.isArmOrThumb() and abi.floatAbi() == .hard) "hf" else "",
1687 }) catch unreachable else switch (os_tag) {
1688 .freebsd => init("/libexec/ld-elf.so.1"),
1689 .netbsd => init("/libexec/ld.elf_so"),
1690 .openbsd => init("/usr/libexec/ld.so"),
1691 .dragonfly => init("/libexec/ld-elf.so.2"),
1692 .solaris, .illumos => init("/lib/64/ld.so.1"),
1693 .linux => switch (cpu.arch) {
1694 .x86,
1695 .sparc,
1696 .sparcel,
1697 => init("/lib/ld-linux.so.2"),
16281698
1629 switch (os_tag) {
1630 .freebsd => return copy(&result, "/libexec/ld-elf.so.1"),
1631 .netbsd => return copy(&result, "/libexec/ld.elf_so"),
1632 .openbsd => return copy(&result, "/usr/libexec/ld.so"),
1633 .dragonfly => return copy(&result, "/libexec/ld-elf.so.2"),
1634 .solaris, .illumos => return copy(&result, "/lib/64/ld.so.1"),
1635 .linux => switch (cpu.arch) {
1636 .x86,
1637 .sparc,
1638 .sparcel,
1639 => return copy(&result, "/lib/ld-linux.so.2"),
1699 .aarch64 => init("/lib/ld-linux-aarch64.so.1"),
1700 .aarch64_be => init("/lib/ld-linux-aarch64_be.so.1"),
1701 .aarch64_32 => init("/lib/ld-linux-aarch64_32.so.1"),
16401702
1641 .aarch64 => return copy(&result, "/lib/ld-linux-aarch64.so.1"),
1642 .aarch64_be => return copy(&result, "/lib/ld-linux-aarch64_be.so.1"),
1643 .aarch64_32 => return copy(&result, "/lib/ld-linux-aarch64_32.so.1"),
1703 .arm,
1704 .armeb,
1705 .thumb,
1706 .thumbeb,
1707 => initFmt("/lib/ld-linux{s}.so.3", .{switch (abi.floatAbi()) {
1708 .hard => "-armhf",
1709 else => "",
1710 }}) catch unreachable,
16441711
1645 .arm,
1646 .armeb,
1647 .thumb,
1648 .thumbeb,
1649 => return copy(&result, switch (abi.floatAbi()) {
1650 .hard => "/lib/ld-linux-armhf.so.3",
1651 else => "/lib/ld-linux.so.3",
1652 }),
1712 .mips,
1713 .mipsel,
1714 .mips64,
1715 .mips64el,
1716 => initFmt("/lib{s}/{s}", .{
1717 switch (abi) {
1718 .gnuabin32, .gnux32 => "32",
1719 .gnuabi64 => "64",
1720 else => "",
1721 },
1722 if (mips.featureSetHas(cpu.features, .nan2008))
1723 "ld-linux-mipsn8.so.1"
1724 else
1725 "ld.so.1",
1726 }) catch unreachable,
1727
1728 .powerpc, .powerpcle => init("/lib/ld.so.1"),
1729 .powerpc64, .powerpc64le => init("/lib64/ld64.so.2"),
1730 .s390x => init("/lib64/ld64.so.1"),
1731 .sparc64 => init("/lib64/ld-linux.so.2"),
1732 .x86_64 => init(switch (abi) {
1733 .gnux32 => "/libx32/ld-linux-x32.so.2",
1734 else => "/lib64/ld-linux-x86-64.so.2",
1735 }),
1736
1737 .riscv32 => init("/lib/ld-linux-riscv32-ilp32.so.1"),
1738 .riscv64 => init("/lib/ld-linux-riscv64-lp64.so.1"),
1739
1740 // Architectures in this list have been verified as not having a standard
1741 // dynamic linker path.
1742 .wasm32,
1743 .wasm64,
1744 .bpfel,
1745 .bpfeb,
1746 .nvptx,
1747 .nvptx64,
1748 .spu_2,
1749 .avr,
1750 .spirv32,
1751 .spirv64,
1752 => none,
16531753
1654 .mips,
1655 .mipsel,
1656 .mips64,
1657 .mips64el,
1658 => {
1659 const lib_suffix = switch (abi) {
1660 .gnuabin32, .gnux32 => "32",
1661 .gnuabi64 => "64",
1662 else => "",
1663 };
1664 const is_nan_2008 = mips.featureSetHas(cpu.features, .nan2008);
1665 const loader = if (is_nan_2008) "ld-linux-mipsn8.so.1" else "ld.so.1";
1666 return print(&result, "/lib{s}/{s}", .{ lib_suffix, loader });
1754 // TODO go over each item in this list and either move it to the above list, or
1755 // implement the standard dynamic linker path code for it.
1756 .arc,
1757 .csky,
1758 .hexagon,
1759 .m68k,
1760 .msp430,
1761 .r600,
1762 .amdgcn,
1763 .tce,
1764 .tcele,
1765 .xcore,
1766 .le32,
1767 .le64,
1768 .amdil,
1769 .amdil64,
1770 .hsail,
1771 .hsail64,
1772 .spir,
1773 .spir64,
1774 .kalimba,
1775 .shave,
1776 .lanai,
1777 .renderscript32,
1778 .renderscript64,
1779 .ve,
1780 .dxil,
1781 .loongarch32,
1782 .loongarch64,
1783 .xtensa,
1784 => none,
16671785 },
16681786
1669 .powerpc, .powerpcle => return copy(&result, "/lib/ld.so.1"),
1670 .powerpc64, .powerpc64le => return copy(&result, "/lib64/ld64.so.2"),
1671 .s390x => return copy(&result, "/lib64/ld64.so.1"),
1672 .sparc64 => return copy(&result, "/lib64/ld-linux.so.2"),
1673 .x86_64 => return copy(&result, switch (abi) {
1674 .gnux32 => "/libx32/ld-linux-x32.so.2",
1675 else => "/lib64/ld-linux-x86-64.so.2",
1676 }),
1677
1678 .riscv32 => return copy(&result, "/lib/ld-linux-riscv32-ilp32.so.1"),
1679 .riscv64 => return copy(&result, "/lib/ld-linux-riscv64-lp64.so.1"),
1787 .ios,
1788 .tvos,
1789 .watchos,
1790 .macos,
1791 => init("/usr/lib/dyld"),
16801792
1681 // Architectures in this list have been verified as not having a standard
1793 // Operating systems in this list have been verified as not having a standard
16821794 // dynamic linker path.
1683 .wasm32,
1684 .wasm64,
1685 .bpfel,
1686 .bpfeb,
1687 .nvptx,
1688 .nvptx64,
1689 .spu_2,
1690 .avr,
1691 .spirv32,
1692 .spirv64,
1693 => return result,
1795 .freestanding,
1796 .uefi,
1797 .windows,
1798 .emscripten,
1799 .wasi,
1800 .opencl,
1801 .glsl450,
1802 .vulkan,
1803 .other,
1804 .plan9,
1805 => none,
1806
1807 // TODO revisit when multi-arch for Haiku is available
1808 .haiku => init("/system/runtime_loader"),
16941809
16951810 // TODO go over each item in this list and either move it to the above list, or
16961811 // implement the standard dynamic linker path code for it.
1697 .arc,
1698 .csky,
1699 .hexagon,
1700 .m68k,
1701 .msp430,
1702 .r600,
1703 .amdgcn,
1704 .tce,
1705 .tcele,
1706 .xcore,
1707 .le32,
1708 .le64,
1709 .amdil,
1710 .amdil64,
1711 .hsail,
1712 .hsail64,
1713 .spir,
1714 .spir64,
1715 .kalimba,
1716 .shave,
1717 .lanai,
1718 .renderscript32,
1719 .renderscript64,
1720 .ve,
1721 .dxil,
1722 .loongarch32,
1723 .loongarch64,
1724 .xtensa,
1725 => return result,
1726 },
1727
1728 .ios,
1729 .tvos,
1730 .watchos,
1731 .macos,
1732 => return copy(&result, "/usr/lib/dyld"),
1733
1734 // Operating systems in this list have been verified as not having a standard
1735 // dynamic linker path.
1736 .freestanding,
1737 .uefi,
1738 .windows,
1739 .emscripten,
1740 .wasi,
1741 .opencl,
1742 .glsl450,
1743 .vulkan,
1744 .other,
1745 .plan9,
1746 => return result,
1747
1748 // TODO revisit when multi-arch for Haiku is available
1749 .haiku => return copy(&result, "/system/runtime_loader"),
1750
1751 // TODO go over each item in this list and either move it to the above list, or
1752 // implement the standard dynamic linker path code for it.
1753 .ananas,
1754 .cloudabi,
1755 .fuchsia,
1756 .kfreebsd,
1757 .lv2,
1758 .zos,
1759 .minix,
1760 .rtems,
1761 .nacl,
1762 .aix,
1763 .cuda,
1764 .nvcl,
1765 .amdhsa,
1766 .ps4,
1767 .ps5,
1768 .elfiamcu,
1769 .mesa3d,
1770 .contiki,
1771 .amdpal,
1772 .hermit,
1773 .hurd,
1774 .driverkit,
1775 .shadermodel,
1776 .liteos,
1777 => return result,
1812 .ananas,
1813 .cloudabi,
1814 .fuchsia,
1815 .kfreebsd,
1816 .lv2,
1817 .zos,
1818 .minix,
1819 .rtems,
1820 .nacl,
1821 .aix,
1822 .cuda,
1823 .nvcl,
1824 .amdhsa,
1825 .ps4,
1826 .ps5,
1827 .elfiamcu,
1828 .mesa3d,
1829 .contiki,
1830 .amdpal,
1831 .hermit,
1832 .hurd,
1833 .driverkit,
1834 .shadermodel,
1835 .liteos,
1836 => none,
1837 };
17781838 }
1779}
1839};
17801840
1781/// 0c spim little-endian MIPS 3000 family
1782/// 1c 68000 Motorola MC68000
1783/// 2c 68020 Motorola MC68020
1784/// 5c arm little-endian ARM
1785/// 6c amd64 AMD64 and compatibles (e.g., Intel EM64T)
1786/// 7c arm64 ARM64 (ARMv8)
1787/// 8c 386 Intel x86, i486, Pentium, etc.
1788/// kc sparc Sun SPARC
1789/// qc power Power PC
1790/// vc mips big-endian MIPS 3000 family
1791pub fn plan9Ext(cpu_arch: Cpu.Arch) [:0]const u8 {
1792 return switch (cpu_arch) {
1793 .arm => ".5",
1794 .x86_64 => ".6",
1795 .aarch64 => ".7",
1796 .x86 => ".8",
1797 .sparc => ".k",
1798 .powerpc, .powerpcle => ".q",
1799 .mips, .mipsel => ".v",
1800 // ISAs without designated characters get 'X' for lack of a better option.
1801 else => ".X",
1802 };
1841pub fn standardDynamicLinkerPath(target: Target) DynamicLinker {
1842 return DynamicLinker.standard(target.cpu, target.os.tag, target.abi);
18031843}
18041844
18051845pub fn maxIntAlignment(target: Target) u16 {
......@@ -2076,7 +2116,7 @@ pub fn c_type_byte_size(t: Target, c_type: CType) u16 {
20762116 16 => 2,
20772117 32 => 4,
20782118 64 => 8,
2079 80 => @as(u16, @intCast(std.mem.alignForward(usize, 10, c_type_alignment(t, .longdouble)))),
2119 80 => @intCast(std.mem.alignForward(usize, 10, c_type_alignment(t, .longdouble))),
20802120 128 => 16,
20812121 else => unreachable,
20822122 },
......@@ -2419,7 +2459,7 @@ pub fn c_type_alignment(target: Target, c_type: CType) u16 {
24192459 // Next-power-of-two-aligned, up to a maximum.
24202460 return @min(
24212461 std.math.ceilPowerOfTwoAssert(u16, (c_type_bit_size(target, c_type) + 7) / 8),
2422 switch (target.cpu.arch) {
2462 @as(u16, switch (target.cpu.arch) {
24232463 .arm, .armeb, .thumb, .thumbeb => switch (target.os.tag) {
24242464 .netbsd => switch (target.abi) {
24252465 .gnueabi,
......@@ -2431,7 +2471,7 @@ pub fn c_type_alignment(target: Target, c_type: CType) u16 {
24312471 .musleabihf,
24322472 => 8,
24332473
2434 else => @as(u16, 4),
2474 else => 4,
24352475 },
24362476 .ios, .tvos, .watchos => 4,
24372477 else => 8,
......@@ -2501,7 +2541,7 @@ pub fn c_type_alignment(target: Target, c_type: CType) u16 {
25012541 .wasm32,
25022542 .wasm64,
25032543 => 16,
2504 },
2544 }),
25052545 );
25062546}
25072547
......@@ -2559,8 +2599,8 @@ pub fn c_type_preferred_alignment(target: Target, c_type: CType) u16 {
25592599 // Next-power-of-two-aligned, up to a maximum.
25602600 return @min(
25612601 std.math.ceilPowerOfTwoAssert(u16, (c_type_bit_size(target, c_type) + 7) / 8),
2562 switch (target.cpu.arch) {
2563 .msp430 => @as(u16, 2),
2602 @as(u16, switch (target.cpu.arch) {
2603 .msp430 => 2,
25642604
25652605 .csky,
25662606 .xcore,
......@@ -2627,7 +2667,7 @@ pub fn c_type_preferred_alignment(target: Target, c_type: CType) u16 {
26272667 .wasm32,
26282668 .wasm64,
26292669 => 16,
2630 },
2670 }),
26312671 );
26322672}
26332673
......@@ -2767,19 +2807,7 @@ fn eqlIgnoreCase(ignore_case: bool, a: []const u8, b: []const u8) bool {
27672807}
27682808
27692809pub fn osArchName(target: std.Target) [:0]const u8 {
2770 return switch (target.os.tag) {
2771 .linux => switch (target.cpu.arch) {
2772 .arm, .armeb, .thumb, .thumbeb => "arm",
2773 .aarch64, .aarch64_be, .aarch64_32 => "aarch64",
2774 .mips, .mipsel, .mips64, .mips64el => "mips",
2775 .powerpc, .powerpcle, .powerpc64, .powerpc64le => "powerpc",
2776 .riscv32, .riscv64 => "riscv",
2777 .sparc, .sparcel, .sparc64 => "sparc",
2778 .x86, .x86_64 => "x86",
2779 else => @tagName(target.cpu.arch),
2780 },
2781 else => @tagName(target.cpu.arch),
2782 };
2810 return target.os.tag.archName(target.cpu.arch);
27832811}
27842812
27852813const Target = @This();
lib/std/Target/Query.zig+35-139
......@@ -124,71 +124,21 @@ pub fn fromTarget(target: Target) Query {
124124}
125125
126126fn updateOsVersionRange(self: *Query, os: Target.Os) void {
127 switch (os.tag) {
128 .freestanding,
129 .ananas,
130 .cloudabi,
131 .fuchsia,
132 .kfreebsd,
133 .lv2,
134 .solaris,
135 .illumos,
136 .zos,
137 .haiku,
138 .minix,
139 .rtems,
140 .nacl,
141 .aix,
142 .cuda,
143 .nvcl,
144 .amdhsa,
145 .ps4,
146 .ps5,
147 .elfiamcu,
148 .mesa3d,
149 .contiki,
150 .amdpal,
151 .hermit,
152 .hurd,
153 .wasi,
154 .emscripten,
155 .driverkit,
156 .shadermodel,
157 .liteos,
158 .uefi,
159 .opencl,
160 .glsl450,
161 .vulkan,
162 .plan9,
163 .other,
164 => {
165 self.os_version_min = .{ .none = {} };
166 self.os_version_max = .{ .none = {} };
127 self.os_version_min, self.os_version_max = switch (os.tag.getVersionRangeTag()) {
128 .none => .{ .{ .none = {} }, .{ .none = {} } },
129 .semver => .{
130 .{ .semver = os.version_range.semver.min },
131 .{ .semver = os.version_range.semver.max },
167132 },
168
169 .freebsd,
170 .macos,
171 .ios,
172 .tvos,
173 .watchos,
174 .netbsd,
175 .openbsd,
176 .dragonfly,
177 => {
178 self.os_version_min = .{ .semver = os.version_range.semver.min };
179 self.os_version_max = .{ .semver = os.version_range.semver.max };
180 },
181
182 .linux => {
183 self.os_version_min = .{ .semver = os.version_range.linux.range.min };
184 self.os_version_max = .{ .semver = os.version_range.linux.range.max };
133 .linux => .{
134 .{ .semver = os.version_range.linux.range.min },
135 .{ .semver = os.version_range.linux.range.max },
185136 },
186
187 .windows => {
188 self.os_version_min = .{ .windows = os.version_range.windows.min };
189 self.os_version_max = .{ .windows = os.version_range.windows.max };
137 .windows => .{
138 .{ .windows = os.version_range.windows.min },
139 .{ .windows = os.version_range.windows.max },
190140 },
191 }
141 };
192142}
193143
194144pub const ParseOptions = struct {
......@@ -278,7 +228,8 @@ pub fn parse(args: ParseOptions) !Query {
278228
279229 const abi_ver_text = abi_it.rest();
280230 if (abi_it.next() != null) {
281 if (Target.isGnuLibC_os_tag_abi(result.os_tag orelse builtin.os.tag, abi)) {
231 const tag = result.os_tag orelse builtin.os.tag;
232 if (tag.isGnuLibC(abi)) {
282233 result.glibc_version = parseVersion(abi_ver_text) catch |err| switch (err) {
283234 error.Overflow => return error.InvalidAbiVersion,
284235 error.InvalidVersion => return error.InvalidAbiVersion,
......@@ -567,88 +518,33 @@ fn parseOs(result: *Query, diags: *ParseOptions.Diagnostics, text: []const u8) !
567518 diags.os_tag = tag;
568519
569520 const version_text = it.rest();
570 if (it.next() == null) return;
571
572 switch (tag) {
573 .freestanding,
574 .ananas,
575 .cloudabi,
576 .fuchsia,
577 .kfreebsd,
578 .lv2,
579 .solaris,
580 .illumos,
581 .zos,
582 .haiku,
583 .minix,
584 .rtems,
585 .nacl,
586 .aix,
587 .cuda,
588 .nvcl,
589 .amdhsa,
590 .ps4,
591 .ps5,
592 .elfiamcu,
593 .mesa3d,
594 .contiki,
595 .amdpal,
596 .hermit,
597 .hurd,
598 .wasi,
599 .emscripten,
600 .uefi,
601 .opencl,
602 .glsl450,
603 .vulkan,
604 .plan9,
605 .driverkit,
606 .shadermodel,
607 .liteos,
608 .other,
609 => return error.InvalidOperatingSystemVersion,
610
611 .freebsd,
612 .macos,
613 .ios,
614 .tvos,
615 .watchos,
616 .netbsd,
617 .openbsd,
618 .linux,
619 .dragonfly,
620 => {
521 if (version_text.len > 0) switch (tag.getVersionRangeTag()) {
522 .none => return error.InvalidOperatingSystemVersion,
523 .semver, .linux => range: {
621524 var range_it = mem.splitSequence(u8, version_text, "...");
622
623 const min_text = range_it.next().?;
624 const min_ver = parseVersion(min_text) catch |err| switch (err) {
625 error.Overflow => return error.InvalidOperatingSystemVersion,
626 error.InvalidVersion => return error.InvalidOperatingSystemVersion,
525 result.os_version_min = .{
526 .semver = parseVersion(range_it.first()) catch |err| switch (err) {
527 error.Overflow => return error.InvalidOperatingSystemVersion,
528 error.InvalidVersion => return error.InvalidOperatingSystemVersion,
529 },
627530 };
628 result.os_version_min = .{ .semver = min_ver };
629
630 const max_text = range_it.next() orelse return;
631 const max_ver = parseVersion(max_text) catch |err| switch (err) {
632 error.Overflow => return error.InvalidOperatingSystemVersion,
633 error.InvalidVersion => return error.InvalidOperatingSystemVersion,
531 result.os_version_max = .{
532 .semver = parseVersion(range_it.next() orelse break :range) catch |err| switch (err) {
533 error.Overflow => return error.InvalidOperatingSystemVersion,
534 error.InvalidVersion => return error.InvalidOperatingSystemVersion,
535 },
634536 };
635 result.os_version_max = .{ .semver = max_ver };
636537 },
637
638 .windows => {
538 .windows => range: {
639539 var range_it = mem.splitSequence(u8, version_text, "...");
640
641 const min_text = range_it.first();
642 const min_ver = std.meta.stringToEnum(Target.Os.WindowsVersion, min_text) orelse
643 return error.InvalidOperatingSystemVersion;
644 result.os_version_min = .{ .windows = min_ver };
645
646 const max_text = range_it.next() orelse return;
647 const max_ver = std.meta.stringToEnum(Target.Os.WindowsVersion, max_text) orelse
648 return error.InvalidOperatingSystemVersion;
649 result.os_version_max = .{ .windows = max_ver };
540 result.os_version_min = .{
541 .windows = try Target.Os.WindowsVersion.parse(range_it.first()),
542 };
543 result.os_version_max = .{
544 .windows = try Target.Os.WindowsVersion.parse(range_it.next() orelse break :range),
545 };
650546 },
651 }
547 };
652548}
653549
654550pub fn eql(a: Query, b: Query) bool {
lib/std/zig/system.zig+22-22
......@@ -430,9 +430,9 @@ pub fn abiAndDynamicLinkerFromFile(
430430 query: Target.Query,
431431) AbiAndDynamicLinkerFromFileError!Target {
432432 var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 align(@alignOf(elf.Elf64_Ehdr)) = undefined;
433 _ = try preadMin(file, &hdr_buf, 0, hdr_buf.len);
434 const hdr32 = @as(*elf.Elf32_Ehdr, @ptrCast(&hdr_buf));
435 const hdr64 = @as(*elf.Elf64_Ehdr, @ptrCast(&hdr_buf));
433 _ = try preadAtLeast(file, &hdr_buf, 0, hdr_buf.len);
434 const hdr32: *elf.Elf32_Ehdr = @ptrCast(&hdr_buf);
435 const hdr64: *elf.Elf64_Ehdr = @ptrCast(&hdr_buf);
436436 if (!mem.eql(u8, hdr32.e_ident[0..4], elf.MAGIC)) return error.InvalidElfMagic;
437437 const elf_endian: std.builtin.Endian = switch (hdr32.e_ident[elf.EI_DATA]) {
438438 elf.ELFDATA2LSB => .little,
......@@ -469,7 +469,7 @@ pub fn abiAndDynamicLinkerFromFile(
469469 // Reserve some bytes so that we can deref the 64-bit struct fields
470470 // even when the ELF file is 32-bits.
471471 const ph_reserve: usize = @sizeOf(elf.Elf64_Phdr) - @sizeOf(elf.Elf32_Phdr);
472 const ph_read_byte_len = try preadMin(file, ph_buf[0 .. ph_buf.len - ph_reserve], phoff, phentsize);
472 const ph_read_byte_len = try preadAtLeast(file, ph_buf[0 .. ph_buf.len - ph_reserve], phoff, phentsize);
473473 var ph_buf_i: usize = 0;
474474 while (ph_buf_i < ph_read_byte_len and ph_i < phnum) : ({
475475 ph_i += 1;
......@@ -484,13 +484,13 @@ pub fn abiAndDynamicLinkerFromFile(
484484 const p_offset = elfInt(is_64, need_bswap, ph32.p_offset, ph64.p_offset);
485485 const p_filesz = elfInt(is_64, need_bswap, ph32.p_filesz, ph64.p_filesz);
486486 if (p_filesz > result.dynamic_linker.buffer.len) return error.NameTooLong;
487 const filesz = @as(usize, @intCast(p_filesz));
488 _ = try preadMin(file, result.dynamic_linker.buffer[0..filesz], p_offset, filesz);
487 const filesz: usize = @intCast(p_filesz);
488 _ = try preadAtLeast(file, result.dynamic_linker.buffer[0..filesz], p_offset, filesz);
489489 // PT_INTERP includes a null byte in filesz.
490490 const len = filesz - 1;
491491 // dynamic_linker.max_byte is "max", not "len".
492492 // We know it will fit in u8 because we check against dynamic_linker.buffer.len above.
493 result.dynamic_linker.max_byte = @as(u8, @intCast(len - 1));
493 result.dynamic_linker.len = @intCast(len);
494494
495495 // Use it to determine ABI.
496496 const full_ld_path = result.dynamic_linker.buffer[0..len];
......@@ -516,7 +516,7 @@ pub fn abiAndDynamicLinkerFromFile(
516516 // Reserve some bytes so that we can deref the 64-bit struct fields
517517 // even when the ELF file is 32-bits.
518518 const dyn_reserve: usize = @sizeOf(elf.Elf64_Dyn) - @sizeOf(elf.Elf32_Dyn);
519 const dyn_read_byte_len = try preadMin(
519 const dyn_read_byte_len = try preadAtLeast(
520520 file,
521521 dyn_buf[0 .. dyn_buf.len - dyn_reserve],
522522 dyn_off,
......@@ -556,14 +556,14 @@ pub fn abiAndDynamicLinkerFromFile(
556556 var sh_buf: [16 * @sizeOf(elf.Elf64_Shdr)]u8 align(@alignOf(elf.Elf64_Shdr)) = undefined;
557557 if (sh_buf.len < shentsize) return error.InvalidElfFile;
558558
559 _ = try preadMin(file, &sh_buf, str_section_off, shentsize);
559 _ = try preadAtLeast(file, &sh_buf, str_section_off, shentsize);
560560 const shstr32: *elf.Elf32_Shdr = @ptrCast(@alignCast(&sh_buf));
561561 const shstr64: *elf.Elf64_Shdr = @ptrCast(@alignCast(&sh_buf));
562562 const shstrtab_off = elfInt(is_64, need_bswap, shstr32.sh_offset, shstr64.sh_offset);
563563 const shstrtab_size = elfInt(is_64, need_bswap, shstr32.sh_size, shstr64.sh_size);
564564 var strtab_buf: [4096:0]u8 = undefined;
565565 const shstrtab_len = @min(shstrtab_size, strtab_buf.len);
566 const shstrtab_read_len = try preadMin(file, &strtab_buf, shstrtab_off, shstrtab_len);
566 const shstrtab_read_len = try preadAtLeast(file, &strtab_buf, shstrtab_off, shstrtab_len);
567567 const shstrtab = strtab_buf[0..shstrtab_read_len];
568568
569569 const shnum = elfInt(is_64, need_bswap, hdr32.e_shnum, hdr64.e_shnum);
......@@ -572,7 +572,7 @@ pub fn abiAndDynamicLinkerFromFile(
572572 // Reserve some bytes so that we can deref the 64-bit struct fields
573573 // even when the ELF file is 32-bits.
574574 const sh_reserve: usize = @sizeOf(elf.Elf64_Shdr) - @sizeOf(elf.Elf32_Shdr);
575 const sh_read_byte_len = try preadMin(
575 const sh_read_byte_len = try preadAtLeast(
576576 file,
577577 sh_buf[0 .. sh_buf.len - sh_reserve],
578578 shoff,
......@@ -604,7 +604,7 @@ pub fn abiAndDynamicLinkerFromFile(
604604 const rp_max_size = ds.size - rpoff;
605605
606606 const strtab_len = @min(rp_max_size, strtab_buf.len);
607 const strtab_read_len = try preadMin(file, &strtab_buf, rpoff_file, strtab_len);
607 const strtab_read_len = try preadAtLeast(file, &strtab_buf, rpoff_file, strtab_len);
608608 const strtab = strtab_buf[0..strtab_read_len];
609609
610610 const rpath_list = mem.sliceTo(strtab, 0);
......@@ -814,9 +814,9 @@ fn glibcVerFromRPath(rpath: []const u8) !std.SemanticVersion {
814814
815815fn glibcVerFromSoFile(file: fs.File) !std.SemanticVersion {
816816 var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 align(@alignOf(elf.Elf64_Ehdr)) = undefined;
817 _ = try preadMin(file, &hdr_buf, 0, hdr_buf.len);
818 const hdr32 = @as(*elf.Elf32_Ehdr, @ptrCast(&hdr_buf));
819 const hdr64 = @as(*elf.Elf64_Ehdr, @ptrCast(&hdr_buf));
817 _ = try preadAtLeast(file, &hdr_buf, 0, hdr_buf.len);
818 const hdr32: *elf.Elf32_Ehdr = @ptrCast(&hdr_buf);
819 const hdr64: *elf.Elf64_Ehdr = @ptrCast(&hdr_buf);
820820 if (!mem.eql(u8, hdr32.e_ident[0..4], elf.MAGIC)) return error.InvalidElfMagic;
821821 const elf_endian: std.builtin.Endian = switch (hdr32.e_ident[elf.EI_DATA]) {
822822 elf.ELFDATA2LSB => .little,
......@@ -838,14 +838,14 @@ fn glibcVerFromSoFile(file: fs.File) !std.SemanticVersion {
838838 var sh_buf: [16 * @sizeOf(elf.Elf64_Shdr)]u8 align(@alignOf(elf.Elf64_Shdr)) = undefined;
839839 if (sh_buf.len < shentsize) return error.InvalidElfFile;
840840
841 _ = try preadMin(file, &sh_buf, str_section_off, shentsize);
841 _ = try preadAtLeast(file, &sh_buf, str_section_off, shentsize);
842842 const shstr32: *elf.Elf32_Shdr = @ptrCast(@alignCast(&sh_buf));
843843 const shstr64: *elf.Elf64_Shdr = @ptrCast(@alignCast(&sh_buf));
844844 const shstrtab_off = elfInt(is_64, need_bswap, shstr32.sh_offset, shstr64.sh_offset);
845845 const shstrtab_size = elfInt(is_64, need_bswap, shstr32.sh_size, shstr64.sh_size);
846846 var strtab_buf: [4096:0]u8 = undefined;
847847 const shstrtab_len = @min(shstrtab_size, strtab_buf.len);
848 const shstrtab_read_len = try preadMin(file, &strtab_buf, shstrtab_off, shstrtab_len);
848 const shstrtab_read_len = try preadAtLeast(file, &strtab_buf, shstrtab_off, shstrtab_len);
849849 const shstrtab = strtab_buf[0..shstrtab_read_len];
850850 const shnum = elfInt(is_64, need_bswap, hdr32.e_shnum, hdr64.e_shnum);
851851 var sh_i: u16 = 0;
......@@ -853,7 +853,7 @@ fn glibcVerFromSoFile(file: fs.File) !std.SemanticVersion {
853853 // Reserve some bytes so that we can deref the 64-bit struct fields
854854 // even when the ELF file is 32-bits.
855855 const sh_reserve: usize = @sizeOf(elf.Elf64_Shdr) - @sizeOf(elf.Elf32_Shdr);
856 const sh_read_byte_len = try preadMin(
856 const sh_read_byte_len = try preadAtLeast(
857857 file,
858858 sh_buf[0 .. sh_buf.len - sh_reserve],
859859 shoff,
......@@ -890,7 +890,7 @@ fn glibcVerFromSoFile(file: fs.File) !std.SemanticVersion {
890890
891891 const dynstr_size: usize = @intCast(dynstr.size);
892892 const dynstr_bytes = buf[0..dynstr_size];
893 _ = try preadMin(file, dynstr_bytes, dynstr.offset, dynstr_bytes.len);
893 _ = try preadAtLeast(file, dynstr_bytes, dynstr.offset, dynstr_bytes.len);
894894 var it = mem.splitScalar(u8, dynstr_bytes, 0);
895895 var max_ver: std.SemanticVersion = .{ .major = 2, .minor = 2, .patch = 5 };
896896 while (it.next()) |s| {
......@@ -1029,7 +1029,7 @@ fn detectAbiAndDynamicLinker(
10291029 };
10301030 errdefer file.close();
10311031
1032 const len = preadMin(file, &buffer, 0, buffer.len) catch |err| switch (err) {
1032 const len = preadAtLeast(file, &buffer, 0, buffer.len) catch |err| switch (err) {
10331033 error.UnexpectedEndOfFile,
10341034 error.UnableToReadElfFile,
10351035 => break :blk file,
......@@ -1083,7 +1083,7 @@ fn defaultAbiAndDynamicLinker(cpu: Target.Cpu, os: Target.Os, query: Target.Quer
10831083 .abi = abi,
10841084 .ofmt = query.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch),
10851085 .dynamic_linker = if (query.dynamic_linker.get() == null)
1086 Target.standardDynamicLinkerPath_cpu_os_abi(cpu, os.tag, abi)
1086 Target.DynamicLinker.standard(cpu, os.tag, abi)
10871087 else
10881088 query.dynamic_linker,
10891089 };
......@@ -1094,7 +1094,7 @@ const LdInfo = struct {
10941094 abi: Target.Abi,
10951095};
10961096
1097fn preadMin(file: fs.File, buf: []u8, offset: u64, min_read_len: usize) !usize {
1097fn preadAtLeast(file: fs.File, buf: []u8, offset: u64, min_read_len: usize) !usize {
10981098 var i: usize = 0;
10991099 while (i < min_read_len) {
11001100 const len = file.pread(buf[i..], offset + i) catch |err| switch (err) {
src/Builtin.zig+3-5
......@@ -140,13 +140,11 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
140140 }),
141141 .windows => |windows| try buffer.writer().print(
142142 \\ .windows = .{{
143 \\ .min = {s},
144 \\ .max = {s},
143 \\ .min = {c},
144 \\ .max = {c},
145145 \\ }}}},
146146 \\
147 ,
148 .{ windows.min, windows.max },
149 ),
147 , .{ windows.min, windows.max }),
150148 }
151149 try buffer.appendSlice(
152150 \\};