authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-04-15 16:14:22-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-04-15 16:14:22-07:00
loga2b834e8c7152f70d71c71107db40b9182909647
tree844b981dc1e99cba2dd81c2e4198e9cbd5a697d1
parentb78b2689ed9955487bf9a719e048bfeb5b230724
parent60d5001ac86573eb05aeb25fdc6374b7dd4cc339
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #19654 from jacobly0/wasi-ver

Target: add wasi os version

4 files changed, 516 insertions(+), 589 deletions(-)

lib/std/Target.zig+456-423
......@@ -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 .emscripten,
161 .driverkit,
162 .shadermodel,
163 .liteos,
164 .uefi,
165 .opencl, // TODO: OpenCL versions
166 .glsl450, // TODO: GLSL versions
167 .vulkan,
168 .plan9,
169 .illumos,
170 .other,
171 => .none,
172
173 .freebsd,
174 .macos,
175 .ios,
176 .tvos,
177 .watchos,
178 .netbsd,
179 .openbsd,
180 .dragonfly,
181 .solaris,
182 .wasi,
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,
......@@ -263,7 +377,6 @@ pub const Os = struct {
263377 .amdpal,
264378 .hermit,
265379 .hurd,
266 .wasi,
267380 .emscripten,
268381 .driverkit,
269382 .shadermodel,
......@@ -275,15 +388,15 @@ pub const Os = struct {
275388 .plan9,
276389 .illumos,
277390 .other,
278 => return .{ .none = {} },
391 => .{ .none = {} },
279392
280 .freebsd => return .{
393 .freebsd => .{
281394 .semver = std.SemanticVersion.Range{
282395 .min = .{ .major = 12, .minor = 0, .patch = 0 },
283396 .max = .{ .major = 14, .minor = 0, .patch = 0 },
284397 },
285398 },
286 .macos => return switch (arch) {
399 .macos => switch (arch) {
287400 .aarch64 => VersionRange{
288401 .semver = .{
289402 .min = .{ .major = 11, .minor = 7, .patch = 1 },
......@@ -298,50 +411,56 @@ pub const Os = struct {
298411 },
299412 else => unreachable,
300413 },
301 .ios => return .{
414 .ios => .{
302415 .semver = .{
303416 .min = .{ .major = 12, .minor = 0, .patch = 0 },
304417 .max = .{ .major = 17, .minor = 1, .patch = 0 },
305418 },
306419 },
307 .watchos => return .{
420 .watchos => .{
308421 .semver = .{
309422 .min = .{ .major = 6, .minor = 0, .patch = 0 },
310423 .max = .{ .major = 10, .minor = 1, .patch = 0 },
311424 },
312425 },
313 .tvos => return .{
426 .tvos => .{
314427 .semver = .{
315428 .min = .{ .major = 13, .minor = 0, .patch = 0 },
316429 .max = .{ .major = 17, .minor = 1, .patch = 0 },
317430 },
318431 },
319 .netbsd => return .{
432 .netbsd => .{
320433 .semver = .{
321434 .min = .{ .major = 8, .minor = 0, .patch = 0 },
322435 .max = .{ .major = 10, .minor = 0, .patch = 0 },
323436 },
324437 },
325 .openbsd => return .{
438 .openbsd => .{
326439 .semver = .{
327440 .min = .{ .major = 6, .minor = 8, .patch = 0 },
328441 .max = .{ .major = 7, .minor = 4, .patch = 0 },
329442 },
330443 },
331 .dragonfly => return .{
444 .dragonfly => .{
332445 .semver = .{
333446 .min = .{ .major = 5, .minor = 8, .patch = 0 },
334447 .max = .{ .major = 6, .minor = 4, .patch = 0 },
335448 },
336449 },
337 .solaris => return .{
450 .solaris => .{
338451 .semver = .{
339452 .min = .{ .major = 5, .minor = 11, .patch = 0 },
340453 .max = .{ .major = 5, .minor = 11, .patch = 0 },
341454 },
342455 },
456 .wasi => .{
457 .semver = .{
458 .min = .{ .major = 0, .minor = 1, .patch = 0 },
459 .max = .{ .major = 0, .minor = 1, .patch = 0 },
460 },
461 },
343462
344 .linux => return .{
463 .linux => .{
345464 .linux = .{
346465 .range = .{
347466 .min = .{ .major = 4, .minor = 19, .patch = 0 },
......@@ -351,13 +470,13 @@ pub const Os = struct {
351470 },
352471 },
353472
354 .windows => return .{
473 .windows => .{
355474 .windows = .{
356475 .min = .win8_1,
357476 .max = WindowsVersion.latest,
358477 },
359478 },
360 }
479 };
361480 }
362481 };
363482
......@@ -370,38 +489,28 @@ pub const Os = struct {
370489
371490 /// Provides a tagged union. `Target` does not store the tag because it is
372491 /// 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 }
492 pub inline fn getVersionRange(os: Os) TaggedVersionRange {
493 return switch (os.tag.getVersionRangeTag()) {
494 .none => .{ .none = {} },
495 .semver => .{ .semver = os.version_range.semver },
496 .linux => .{ .linux = os.version_range.linux },
497 .windows => .{ .windows = os.version_range.windows },
498 };
391499 }
392500
393501 /// Checks if system is guaranteed to be at least `version` or older than `version`.
394502 /// 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,
503 pub inline fn isAtLeast(os: Os, comptime tag: Tag, ver: switch (tag.getVersionRangeTag()) {
504 .none => void,
505 .semver, .linux => std.SemanticVersion,
397506 .windows => WindowsVersion,
398507 }) ?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),
508 return if (os.tag != tag) false else switch (tag.getVersionRangeTag()) {
509 .none => true,
510 inline .semver,
511 .linux,
512 .windows,
513 => |field| @field(os.version_range, @tagName(field)).isAtLeast(ver),
405514 };
406515 }
407516
......@@ -528,11 +637,8 @@ pub const Abi = enum {
528637 mesh,
529638 amplification,
530639
531 pub fn default(arch: Cpu.Arch, target_os: Os) Abi {
532 if (arch.isWasm()) {
533 return .musl;
534 }
535 switch (target_os.tag) {
640 pub fn default(arch: Cpu.Arch, os: Os) Abi {
641 return if (arch.isWasm()) .musl else switch (os.tag) {
536642 .freestanding,
537643 .ananas,
538644 .cloudabi,
......@@ -554,7 +660,7 @@ pub const Abi = enum {
554660 .amdpal,
555661 .hermit,
556662 .other,
557 => return .eabi,
663 => .eabi,
558664 .openbsd,
559665 .freebsd,
560666 .fuchsia,
......@@ -563,12 +669,12 @@ pub const Abi = enum {
563669 .hurd,
564670 .haiku,
565671 .windows,
566 => return .gnu,
567 .uefi => return .msvc,
672 => .gnu,
673 .uefi => .msvc,
568674 .linux,
569675 .wasi,
570676 .emscripten,
571 => return .musl,
677 => .musl,
572678 .opencl, // TODO: SPIR-V ABIs with Linkage capability
573679 .glsl450,
574680 .vulkan,
......@@ -582,8 +688,8 @@ pub const Abi = enum {
582688 .liteos, // TODO: audit this
583689 .solaris,
584690 .illumos,
585 => return .none,
586 }
691 => .none,
692 };
587693 }
588694
589695 pub inline fn isGnu(abi: Abi) bool {
......@@ -635,7 +741,7 @@ pub const ObjectFormat = enum {
635741 /// Nvidia PTX format
636742 nvptx,
637743
638 pub fn fileExt(of: ObjectFormat, cpu_arch: Cpu.Arch) [:0]const u8 {
744 pub fn fileExt(of: ObjectFormat, arch: Cpu.Arch) [:0]const u8 {
639745 return switch (of) {
640746 .coff => ".obj",
641747 .elf, .macho, .wasm => ".o",
......@@ -643,18 +749,18 @@ pub const ObjectFormat = enum {
643749 .spirv => ".spv",
644750 .hex => ".ihex",
645751 .raw => ".bin",
646 .plan9 => plan9Ext(cpu_arch),
752 .plan9 => arch.plan9Ext(),
647753 .nvptx => ".ptx",
648754 .dxcontainer => ".dxil",
649755 };
650756 }
651757
652 pub fn default(os_tag: Os.Tag, cpu_arch: Cpu.Arch) ObjectFormat {
758 pub fn default(os_tag: Os.Tag, arch: Cpu.Arch) ObjectFormat {
653759 return switch (os_tag) {
654760 .windows, .uefi => .coff,
655761 .ios, .macos, .watchos, .tvos => .macho,
656762 .plan9 => .plan9,
657 else => return switch (cpu_arch) {
763 else => switch (arch) {
658764 .wasm32, .wasm64 => .wasm,
659765 .spirv32, .spirv64 => .spirv,
660766 .nvptx, .nvptx64 => .nvptx,
......@@ -725,14 +831,14 @@ pub const Cpu = struct {
725831
726832 pub fn isEnabled(set: Set, arch_feature_index: Index) bool {
727833 const usize_index = arch_feature_index / @bitSizeOf(usize);
728 const bit_index = @as(ShiftInt, @intCast(arch_feature_index % @bitSizeOf(usize)));
834 const bit_index: ShiftInt = @intCast(arch_feature_index % @bitSizeOf(usize));
729835 return (set.ints[usize_index] & (@as(usize, 1) << bit_index)) != 0;
730836 }
731837
732838 /// Adds the specified feature but not its dependencies.
733839 pub fn addFeature(set: *Set, arch_feature_index: Index) void {
734840 const usize_index = arch_feature_index / @bitSizeOf(usize);
735 const bit_index = @as(ShiftInt, @intCast(arch_feature_index % @bitSizeOf(usize)));
841 const bit_index: ShiftInt = @intCast(arch_feature_index % @bitSizeOf(usize));
736842 set.ints[usize_index] |= @as(usize, 1) << bit_index;
737843 }
738844
......@@ -751,7 +857,7 @@ pub const Cpu = struct {
751857 /// Removes the specified feature but not its dependents.
752858 pub fn removeFeature(set: *Set, arch_feature_index: Index) void {
753859 const usize_index = arch_feature_index / @bitSizeOf(usize);
754 const bit_index = @as(ShiftInt, @intCast(arch_feature_index % @bitSizeOf(usize)));
860 const bit_index: ShiftInt = @intCast(arch_feature_index % @bitSizeOf(usize));
755861 set.ints[usize_index] &= ~(@as(usize, 1) << bit_index);
756862 }
757863
......@@ -773,7 +879,7 @@ pub const Cpu = struct {
773879 var old = set.ints;
774880 while (true) {
775881 for (all_features_list, 0..) |feature, index_usize| {
776 const index = @as(Index, @intCast(index_usize));
882 const index: Index = @intCast(index_usize);
777883 if (set.isEnabled(index)) {
778884 set.addFeatureSet(feature.dependencies);
779885 }
......@@ -785,7 +891,7 @@ pub const Cpu = struct {
785891 }
786892
787893 pub fn asBytes(set: *const Set) *const [byte_count]u8 {
788 return @as(*const [byte_count]u8, @ptrCast(&set.ints));
894 return std.mem.sliceAsBytes(&set.ints)[0..byte_count];
789895 }
790896
791897 pub fn eql(set: Set, other_set: Set) bool {
......@@ -1231,7 +1337,7 @@ pub const Cpu = struct {
12311337 }
12321338
12331339 /// Returns a name that matches the lib/std/target/* source file name.
1234 pub fn genericName(arch: Arch) []const u8 {
1340 pub fn genericName(arch: Arch) [:0]const u8 {
12351341 return switch (arch) {
12361342 .arm, .armeb, .thumb, .thumbeb => "arm",
12371343 .aarch64, .aarch64_be, .aarch64_32 => "aarch64",
......@@ -1320,6 +1426,30 @@ pub const Cpu = struct {
13201426 const finalized = array;
13211427 return &finalized;
13221428 }
1429
1430 /// 0c spim little-endian MIPS 3000 family
1431 /// 1c 68000 Motorola MC68000
1432 /// 2c 68020 Motorola MC68020
1433 /// 5c arm little-endian ARM
1434 /// 6c amd64 AMD64 and compatibles (e.g., Intel EM64T)
1435 /// 7c arm64 ARM64 (ARMv8)
1436 /// 8c 386 Intel x86, i486, Pentium, etc.
1437 /// kc sparc Sun SPARC
1438 /// qc power Power PC
1439 /// vc mips big-endian MIPS 3000 family
1440 pub fn plan9Ext(arch: Cpu.Arch) [:0]const u8 {
1441 return switch (arch) {
1442 .arm => ".5",
1443 .x86_64 => ".6",
1444 .aarch64 => ".7",
1445 .x86 => ".8",
1446 .sparc => ".k",
1447 .powerpc, .powerpcle => ".q",
1448 .mips, .mipsel => ".v",
1449 // ISAs without designated characters get 'X' for lack of a better option.
1450 else => ".X",
1451 };
1452 }
13231453 };
13241454
13251455 pub const Model = struct {
......@@ -1399,112 +1529,76 @@ pub const Cpu = struct {
13991529 }
14001530};
14011531
1402pub fn zigTriple(self: Target, allocator: Allocator) Allocator.Error![]u8 {
1403 return Query.fromTarget(self).zigTriple(allocator);
1532pub fn zigTriple(target: Target, allocator: Allocator) Allocator.Error![]u8 {
1533 return Query.fromTarget(target).zigTriple(allocator);
14041534}
14051535
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) });
1536pub fn linuxTripleSimple(allocator: Allocator, arch: Cpu.Arch, os_tag: Os.Tag, abi: Abi) ![]u8 {
1537 return std.fmt.allocPrint(allocator, "{s}-{s}-{s}", .{ @tagName(arch), @tagName(os_tag), @tagName(abi) });
14081538}
14091539
1410pub fn linuxTriple(self: Target, allocator: Allocator) ![]u8 {
1411 return linuxTripleSimple(allocator, self.cpu.arch, self.os.tag, self.abi);
1540pub fn linuxTriple(target: Target, allocator: Allocator) ![]u8 {
1541 return linuxTripleSimple(allocator, target.cpu.arch, target.os.tag, target.abi);
14121542}
14131543
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 }
1438}
1439
1440pub fn staticLibSuffix(self: Target) [:0]const u8 {
1441 return staticLibSuffix_os_abi(self.os.tag, self.abi);
1442}
1443
1444pub fn dynamicLibSuffix(self: Target) [:0]const u8 {
1445 return self.os.tag.dynamicLibSuffix();
1544pub fn exeFileExt(target: Target) [:0]const u8 {
1545 return target.os.tag.exeFileExt(target.cpu.arch);
14461546}
14471547
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 }
1548pub fn staticLibSuffix(target: Target) [:0]const u8 {
1549 return target.os.tag.staticLibSuffix(target.abi);
14561550}
14571551
1458pub fn libPrefix(self: Target) [:0]const u8 {
1459 return libPrefix_os_abi(self.os.tag, self.abi);
1552pub fn dynamicLibSuffix(target: Target) [:0]const u8 {
1553 return target.os.tag.dynamicLibSuffix();
14601554}
14611555
1462pub inline fn isMinGW(self: Target) bool {
1463 return self.os.tag == .windows and self.isGnu();
1556pub fn libPrefix(target: Target) [:0]const u8 {
1557 return target.os.tag.libPrefix(target.abi);
14641558}
14651559
1466pub inline fn isGnu(self: Target) bool {
1467 return self.abi.isGnu();
1560pub inline fn isMinGW(target: Target) bool {
1561 return target.os.tag == .windows and target.isGnu();
14681562}
14691563
1470pub inline fn isMusl(self: Target) bool {
1471 return self.abi.isMusl();
1564pub inline fn isGnu(target: Target) bool {
1565 return target.abi.isGnu();
14721566}
14731567
1474pub inline fn isAndroid(self: Target) bool {
1475 return self.abi == .android;
1568pub inline fn isMusl(target: Target) bool {
1569 return target.abi.isMusl();
14761570}
14771571
1478pub inline fn isWasm(self: Target) bool {
1479 return self.cpu.arch.isWasm();
1572pub inline fn isAndroid(target: Target) bool {
1573 return target.abi == .android;
14801574}
14811575
1482pub inline fn isDarwin(self: Target) bool {
1483 return self.os.tag.isDarwin();
1576pub inline fn isWasm(target: Target) bool {
1577 return target.cpu.arch.isWasm();
14841578}
14851579
1486pub inline fn isBSD(self: Target) bool {
1487 return self.os.tag.isBSD();
1580pub inline fn isDarwin(target: Target) bool {
1581 return target.os.tag.isDarwin();
14881582}
14891583
1490pub inline fn isBpfFreestanding(self: Target) bool {
1491 return self.cpu.arch.isBpf() and self.os.tag == .freestanding;
1584pub inline fn isBSD(target: Target) bool {
1585 return target.os.tag.isBSD();
14921586}
14931587
1494pub inline fn isGnuLibC_os_tag_abi(os_tag: Os.Tag, abi: Abi) bool {
1495 return os_tag == .linux and abi.isGnu();
1588pub inline fn isBpfFreestanding(target: Target) bool {
1589 return target.cpu.arch.isBpf() and target.os.tag == .freestanding;
14961590}
14971591
1498pub inline fn isGnuLibC(self: Target) bool {
1499 return isGnuLibC_os_tag_abi(self.os.tag, self.abi);
1592pub inline fn isGnuLibC(target: Target) bool {
1593 return target.os.tag.isGnuLibC(target.abi);
15001594}
15011595
1502pub inline fn supportsNewStackCall(self: Target) bool {
1503 return !self.cpu.arch.isWasm();
1596pub inline fn supportsNewStackCall(target: Target) bool {
1597 return !target.cpu.arch.isWasm();
15041598}
15051599
1506pub inline fn isSpirV(self: Target) bool {
1507 return self.cpu.arch.isSpirV();
1600pub inline fn isSpirV(target: Target) bool {
1601 return target.cpu.arch.isSpirV();
15081602}
15091603
15101604pub const FloatAbi = enum {
......@@ -1512,15 +1606,15 @@ pub const FloatAbi = enum {
15121606 soft,
15131607};
15141608
1515pub inline fn getFloatAbi(self: Target) FloatAbi {
1516 return self.abi.floatAbi();
1609pub inline fn getFloatAbi(target: Target) FloatAbi {
1610 return target.abi.floatAbi();
15171611}
15181612
1519pub inline fn hasDynamicLinker(self: Target) bool {
1520 if (self.cpu.arch.isWasm()) {
1613pub inline fn hasDynamicLinker(target: Target) bool {
1614 if (target.cpu.arch.isWasm()) {
15211615 return false;
15221616 }
1523 switch (self.os.tag) {
1617 switch (target.os.tag) {
15241618 .freestanding,
15251619 .ios,
15261620 .tvos,
......@@ -1547,259 +1641,210 @@ pub const DynamicLinker = struct {
15471641
15481642 /// Used to construct the dynamic linker path. This field should not be used
15491643 /// directly. See `get` and `set`.
1550 max_byte: ?u8,
1644 len: u8,
15511645
1552 pub const none: DynamicLinker = .{
1553 .buffer = undefined,
1554 .max_byte = null,
1555 };
1646 pub const none: DynamicLinker = .{ .buffer = undefined, .len = 0 };
15561647
15571648 /// 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;
1649 pub fn init(maybe_path: ?[]const u8) DynamicLinker {
1650 var dl: DynamicLinker = undefined;
1651 dl.set(maybe_path);
1652 return dl;
1653 }
1654
1655 pub fn initFmt(comptime fmt_str: []const u8, args: anytype) !DynamicLinker {
1656 var dl: DynamicLinker = undefined;
1657 try dl.setFmt(fmt_str, args);
1658 return dl;
15621659 }
15631660
15641661 /// 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];
1662 pub fn get(dl: *const DynamicLinker) ?[]const u8 {
1663 return if (dl.len > 0) dl.buffer[0..dl.len] else null;
15681664 }
15691665
15701666 /// 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 }
1667 pub fn set(dl: *DynamicLinker, maybe_path: ?[]const u8) void {
1668 const path = maybe_path orelse "";
1669 @memcpy(dl.buffer[0..path.len], path);
1670 dl.len = @intCast(path.len);
15781671 }
15791672
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);
1673 /// Asserts that the length is less than or equal to 255 bytes.
1674 pub fn setFmt(dl: *DynamicLinker, comptime fmt_str: []const u8, args: anytype) !void {
1675 dl.len = @intCast((try std.fmt.bufPrint(&dl.buffer, fmt_str, args)).len);
15871676 }
1588};
15891677
1590pub fn standardDynamicLinkerPath(target: Target) DynamicLinker {
1591 return standardDynamicLinkerPath_cpu_os_abi(target.cpu, target.os.tag, target.abi);
1592}
1593
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});
1678 pub fn eql(lhs: DynamicLinker, rhs: DynamicLinker) bool {
1679 return std.mem.eql(u8, lhs.buffer[0..lhs.len], rhs.buffer[0..rhs.len]);
16131680 }
16141681
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 }
1682 pub fn standard(cpu: Cpu, os_tag: Os.Tag, abi: Abi) DynamicLinker {
1683 return if (abi == .android) initFmt("/system/bin/linker{s}", .{
1684 if (ptrBitWidth_cpu_abi(cpu, abi) == 64) "64" else "",
1685 }) catch unreachable else if (abi.isMusl()) return initFmt("/lib/ld-musl-{s}{s}.so.1", .{
1686 @tagName(switch (cpu.arch) {
1687 .thumb => .arm,
1688 .thumbeb => .armeb,
1689 else => cpu.arch,
1690 }),
1691 if (cpu.arch.isArmOrThumb() and abi.floatAbi() == .hard) "hf" else "",
1692 }) catch unreachable else switch (os_tag) {
1693 .freebsd => init("/libexec/ld-elf.so.1"),
1694 .netbsd => init("/libexec/ld.elf_so"),
1695 .openbsd => init("/usr/libexec/ld.so"),
1696 .dragonfly => init("/libexec/ld-elf.so.2"),
1697 .solaris, .illumos => init("/lib/64/ld.so.1"),
1698 .linux => switch (cpu.arch) {
1699 .x86,
1700 .sparc,
1701 .sparcel,
1702 => init("/lib/ld-linux.so.2"),
16281703
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"),
1704 .aarch64 => init("/lib/ld-linux-aarch64.so.1"),
1705 .aarch64_be => init("/lib/ld-linux-aarch64_be.so.1"),
1706 .aarch64_32 => init("/lib/ld-linux-aarch64_32.so.1"),
16401707
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"),
1708 .arm,
1709 .armeb,
1710 .thumb,
1711 .thumbeb,
1712 => initFmt("/lib/ld-linux{s}.so.3", .{switch (abi.floatAbi()) {
1713 .hard => "-armhf",
1714 else => "",
1715 }}) catch unreachable,
16441716
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 }),
1717 .mips,
1718 .mipsel,
1719 .mips64,
1720 .mips64el,
1721 => initFmt("/lib{s}/{s}", .{
1722 switch (abi) {
1723 .gnuabin32, .gnux32 => "32",
1724 .gnuabi64 => "64",
1725 else => "",
1726 },
1727 if (mips.featureSetHas(cpu.features, .nan2008))
1728 "ld-linux-mipsn8.so.1"
1729 else
1730 "ld.so.1",
1731 }) catch unreachable,
1732
1733 .powerpc, .powerpcle => init("/lib/ld.so.1"),
1734 .powerpc64, .powerpc64le => init("/lib64/ld64.so.2"),
1735 .s390x => init("/lib64/ld64.so.1"),
1736 .sparc64 => init("/lib64/ld-linux.so.2"),
1737 .x86_64 => init(switch (abi) {
1738 .gnux32 => "/libx32/ld-linux-x32.so.2",
1739 else => "/lib64/ld-linux-x86-64.so.2",
1740 }),
1741
1742 .riscv32 => init("/lib/ld-linux-riscv32-ilp32.so.1"),
1743 .riscv64 => init("/lib/ld-linux-riscv64-lp64.so.1"),
1744
1745 // Architectures in this list have been verified as not having a standard
1746 // dynamic linker path.
1747 .wasm32,
1748 .wasm64,
1749 .bpfel,
1750 .bpfeb,
1751 .nvptx,
1752 .nvptx64,
1753 .spu_2,
1754 .avr,
1755 .spirv32,
1756 .spirv64,
1757 => none,
16531758
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 });
1759 // TODO go over each item in this list and either move it to the above list, or
1760 // implement the standard dynamic linker path code for it.
1761 .arc,
1762 .csky,
1763 .hexagon,
1764 .m68k,
1765 .msp430,
1766 .r600,
1767 .amdgcn,
1768 .tce,
1769 .tcele,
1770 .xcore,
1771 .le32,
1772 .le64,
1773 .amdil,
1774 .amdil64,
1775 .hsail,
1776 .hsail64,
1777 .spir,
1778 .spir64,
1779 .kalimba,
1780 .shave,
1781 .lanai,
1782 .renderscript32,
1783 .renderscript64,
1784 .ve,
1785 .dxil,
1786 .loongarch32,
1787 .loongarch64,
1788 .xtensa,
1789 => none,
16671790 },
16681791
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"),
1792 .ios,
1793 .tvos,
1794 .watchos,
1795 .macos,
1796 => init("/usr/lib/dyld"),
16801797
1681 // Architectures in this list have been verified as not having a standard
1798 // Operating systems in this list have been verified as not having a standard
16821799 // 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,
1800 .freestanding,
1801 .uefi,
1802 .windows,
1803 .emscripten,
1804 .wasi,
1805 .opencl,
1806 .glsl450,
1807 .vulkan,
1808 .other,
1809 .plan9,
1810 => none,
1811
1812 // TODO revisit when multi-arch for Haiku is available
1813 .haiku => init("/system/runtime_loader"),
16941814
16951815 // TODO go over each item in this list and either move it to the above list, or
16961816 // 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,
1817 .ananas,
1818 .cloudabi,
1819 .fuchsia,
1820 .kfreebsd,
1821 .lv2,
1822 .zos,
1823 .minix,
1824 .rtems,
1825 .nacl,
1826 .aix,
1827 .cuda,
1828 .nvcl,
1829 .amdhsa,
1830 .ps4,
1831 .ps5,
1832 .elfiamcu,
1833 .mesa3d,
1834 .contiki,
1835 .amdpal,
1836 .hermit,
1837 .hurd,
1838 .driverkit,
1839 .shadermodel,
1840 .liteos,
1841 => none,
1842 };
17781843 }
1779}
1844};
17801845
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 };
1846pub fn standardDynamicLinkerPath(target: Target) DynamicLinker {
1847 return DynamicLinker.standard(target.cpu, target.os.tag, target.abi);
18031848}
18041849
18051850pub fn maxIntAlignment(target: Target) u16 {
......@@ -2076,7 +2121,7 @@ pub fn c_type_byte_size(t: Target, c_type: CType) u16 {
20762121 16 => 2,
20772122 32 => 4,
20782123 64 => 8,
2079 80 => @as(u16, @intCast(std.mem.alignForward(usize, 10, c_type_alignment(t, .longdouble)))),
2124 80 => @intCast(std.mem.alignForward(usize, 10, c_type_alignment(t, .longdouble))),
20802125 128 => 16,
20812126 else => unreachable,
20822127 },
......@@ -2419,7 +2464,7 @@ pub fn c_type_alignment(target: Target, c_type: CType) u16 {
24192464 // Next-power-of-two-aligned, up to a maximum.
24202465 return @min(
24212466 std.math.ceilPowerOfTwoAssert(u16, (c_type_bit_size(target, c_type) + 7) / 8),
2422 switch (target.cpu.arch) {
2467 @as(u16, switch (target.cpu.arch) {
24232468 .arm, .armeb, .thumb, .thumbeb => switch (target.os.tag) {
24242469 .netbsd => switch (target.abi) {
24252470 .gnueabi,
......@@ -2431,7 +2476,7 @@ pub fn c_type_alignment(target: Target, c_type: CType) u16 {
24312476 .musleabihf,
24322477 => 8,
24332478
2434 else => @as(u16, 4),
2479 else => 4,
24352480 },
24362481 .ios, .tvos, .watchos => 4,
24372482 else => 8,
......@@ -2501,7 +2546,7 @@ pub fn c_type_alignment(target: Target, c_type: CType) u16 {
25012546 .wasm32,
25022547 .wasm64,
25032548 => 16,
2504 },
2549 }),
25052550 );
25062551}
25072552
......@@ -2559,8 +2604,8 @@ pub fn c_type_preferred_alignment(target: Target, c_type: CType) u16 {
25592604 // Next-power-of-two-aligned, up to a maximum.
25602605 return @min(
25612606 std.math.ceilPowerOfTwoAssert(u16, (c_type_bit_size(target, c_type) + 7) / 8),
2562 switch (target.cpu.arch) {
2563 .msp430 => @as(u16, 2),
2607 @as(u16, switch (target.cpu.arch) {
2608 .msp430 => 2,
25642609
25652610 .csky,
25662611 .xcore,
......@@ -2627,7 +2672,7 @@ pub fn c_type_preferred_alignment(target: Target, c_type: CType) u16 {
26272672 .wasm32,
26282673 .wasm64,
26292674 => 16,
2630 },
2675 }),
26312676 );
26322677}
26332678
......@@ -2767,19 +2812,7 @@ fn eqlIgnoreCase(ignore_case: bool, a: []const u8, b: []const u8) bool {
27672812}
27682813
27692814pub 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 };
2815 return target.os.tag.archName(target.cpu.arch);
27832816}
27842817
27852818const 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 \\};