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 {...@@ -81,14 +81,48 @@ pub const Os = struct {
81 return tag == .solaris or tag == .illumos;81 return tag == .solaris or tag == .illumos;
82 }82 }
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
84 pub fn dynamicLibSuffix(tag: Tag) [:0]const u8 {106 pub fn dynamicLibSuffix(tag: Tag) [:0]const u8 {
85 if (tag.isDarwin()) {107 return switch (tag) {
86 return ".dylib";108 .windows, .uefi => ".dll",
87 }109 .ios, .macos, .watchos, .tvos => ".dylib",
88 switch (tag) {110 else => ".so",
89 .windows => return ".dll",111 };
90 else => return ".so",112 }
91 }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();
92 }126 }
93127
94 pub fn defaultVersionRange(tag: Tag, arch: Cpu.Arch) Os {128 pub fn defaultVersionRange(tag: Tag, arch: Cpu.Arch) Os {
...@@ -97,6 +131,78 @@ pub const Os = struct {...@@ -97,6 +131,78 @@ pub const Os = struct {
97 .version_range = VersionRange.default(tag, arch),131 .version_range = VersionRange.default(tag, arch),
98 };132 };
99 }133 }
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 }
100 };206 };
101207
102 /// Based on NTDDI version constants from208 /// Based on NTDDI version constants from
...@@ -142,52 +248,60 @@ pub const Os = struct {...@@ -142,52 +248,60 @@ pub const Os = struct {
142 19042, //win10_fe aka win10_20h2248 19042, //win10_fe aka win10_20h2
143 };249 };
144250
145 /// Returns whether the first version `self` is newer (greater) than or equal to the second version `ver`.251 /// Returns whether the first version `ver` is newer (greater) than or equal to the second version `ver`.
146 pub inline fn isAtLeast(self: WindowsVersion, ver: WindowsVersion) bool {252 pub inline fn isAtLeast(ver: WindowsVersion, min_ver: WindowsVersion) bool {
147 return @intFromEnum(self) >= @intFromEnum(ver);253 return @intFromEnum(ver) >= @intFromEnum(min_ver);
148 }254 }
149255
150 pub const Range = struct {256 pub const Range = struct {
151 min: WindowsVersion,257 min: WindowsVersion,
152 max: WindowsVersion,258 max: WindowsVersion,
153259
154 pub inline fn includesVersion(self: Range, ver: WindowsVersion) bool {260 pub inline fn includesVersion(range: Range, ver: WindowsVersion) bool {
155 return @intFromEnum(ver) >= @intFromEnum(self.min) and @intFromEnum(ver) <= @intFromEnum(self.max);261 return @intFromEnum(ver) >= @intFromEnum(range.min) and
262 @intFromEnum(ver) <= @intFromEnum(range.max);
156 }263 }
157264
158 /// Checks if system is guaranteed to be at least `version` or older than `version`.265 /// Checks if system is guaranteed to be at least `version` or older than `version`.
159 /// Returns `null` if a runtime check is required.266 /// Returns `null` if a runtime check is required.
160 pub inline fn isAtLeast(self: Range, ver: WindowsVersion) ?bool {267 pub inline fn isAtLeast(range: Range, min_ver: WindowsVersion) ?bool {
161 if (@intFromEnum(self.min) >= @intFromEnum(ver)) return true;268 if (@intFromEnum(range.min) >= @intFromEnum(min_ver)) return true;
162 if (@intFromEnum(self.max) < @intFromEnum(ver)) return false;269 if (@intFromEnum(range.max) < @intFromEnum(min_ver)) return false;
163 return null;270 return null;
164 }271 }
165 };272 };
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
167 /// This function is defined to serialize a Zig source code representation of this280 /// This function is defined to serialize a Zig source code representation of this
168 /// type, that, when parsed, will deserialize into the same data.281 /// type, that, when parsed, will deserialize into the same data.
169 pub fn format(282 pub fn format(
170 self: WindowsVersion,283 ver: WindowsVersion,
171 comptime fmt: []const u8,284 comptime fmt_str: []const u8,
172 _: std.fmt.FormatOptions,285 _: std.fmt.FormatOptions,
173 out_stream: anytype,286 writer: anytype,
174 ) !void {287 ) @TypeOf(writer).Error!void {
175 if (comptime std.mem.eql(u8, fmt, "s")) {288 const maybe_name = std.enums.tagName(WindowsVersion, ver);
176 if (@intFromEnum(self) >= @intFromEnum(WindowsVersion.nt4) and @intFromEnum(self) <= @intFromEnum(WindowsVersion.latest)) {289 if (comptime std.mem.eql(u8, fmt_str, "s")) {
177 try std.fmt.format(out_stream, ".{s}", .{@tagName(self)});290 if (maybe_name) |name|
178 } else {291 try writer.print(".{s}", .{name})
179 // TODO this code path breaks zig triples, but it is used in `builtin`292 else
180 try std.fmt.format(out_stream, "@enumFromInt(Target.Os.WindowsVersion, 0x{X:0>8})", .{@intFromEnum(self)});293 try writer.print(".{d}", .{@intFromEnum(ver)});
181 }294 } else if (comptime std.mem.eql(u8, fmt_str, "c")) {
182 } else if (fmt.len == 0) {295 if (maybe_name) |name|
183 if (@intFromEnum(self) >= @intFromEnum(WindowsVersion.nt4) and @intFromEnum(self) <= @intFromEnum(WindowsVersion.latest)) {296 try writer.print(".{s}", .{name})
184 try std.fmt.format(out_stream, "WindowsVersion.{s}", .{@tagName(self)});297 else
185 } else {298 try writer.print("@enumFromInt(0x{X:0>8})", .{@intFromEnum(ver)});
186 try std.fmt.format(out_stream, "WindowsVersion(0x{X:0>8})", .{@intFromEnum(self)});299 } else if (fmt_str.len == 0) {
187 }300 if (maybe_name) |name|
188 } else {301 try writer.print("WindowsVersion.{s}", .{name})
189 std.fmt.invalidFmtError(fmt, self);302 else
190 }303 try writer.print("WindowsVersion(0x{X:0>8})", .{@intFromEnum(ver)});
304 } else std.fmt.invalidFmtError(fmt_str, ver);
191 }305 }
192 };306 };
193307
...@@ -195,14 +309,14 @@ pub const Os = struct {...@@ -195,14 +309,14 @@ pub const Os = struct {
195 range: std.SemanticVersion.Range,309 range: std.SemanticVersion.Range,
196 glibc: std.SemanticVersion,310 glibc: std.SemanticVersion,
197311
198 pub inline fn includesVersion(self: LinuxVersionRange, ver: std.SemanticVersion) bool {312 pub inline fn includesVersion(range: LinuxVersionRange, ver: std.SemanticVersion) bool {
199 return self.range.includesVersion(ver);313 return range.range.includesVersion(ver);
200 }314 }
201315
202 /// Checks if system is guaranteed to be at least `version` or older than `version`.316 /// Checks if system is guaranteed to be at least `version` or older than `version`.
203 /// Returns `null` if a runtime check is required.317 /// Returns `null` if a runtime check is required.
204 pub inline fn isAtLeast(self: LinuxVersionRange, ver: std.SemanticVersion) ?bool {318 pub inline fn isAtLeast(range: LinuxVersionRange, ver: std.SemanticVersion) ?bool {
205 return self.range.isAtLeast(ver);319 return range.range.isAtLeast(ver);
206 }320 }
207 };321 };
208322
...@@ -239,7 +353,7 @@ pub const Os = struct {...@@ -239,7 +353,7 @@ pub const Os = struct {
239 /// The default `VersionRange` represents the range that the Zig Standard Library353 /// The default `VersionRange` represents the range that the Zig Standard Library
240 /// bases its abstractions on.354 /// bases its abstractions on.
241 pub fn default(tag: Tag, arch: Cpu.Arch) VersionRange {355 pub fn default(tag: Tag, arch: Cpu.Arch) VersionRange {
242 switch (tag) {356 return switch (tag) {
243 .freestanding,357 .freestanding,
244 .ananas,358 .ananas,
245 .cloudabi,359 .cloudabi,
...@@ -263,7 +377,6 @@ pub const Os = struct {...@@ -263,7 +377,6 @@ pub const Os = struct {
263 .amdpal,377 .amdpal,
264 .hermit,378 .hermit,
265 .hurd,379 .hurd,
266 .wasi,
267 .emscripten,380 .emscripten,
268 .driverkit,381 .driverkit,
269 .shadermodel,382 .shadermodel,
...@@ -275,15 +388,15 @@ pub const Os = struct {...@@ -275,15 +388,15 @@ pub const Os = struct {
275 .plan9,388 .plan9,
276 .illumos,389 .illumos,
277 .other,390 .other,
278 => return .{ .none = {} },391 => .{ .none = {} },
279392
280 .freebsd => return .{393 .freebsd => .{
281 .semver = std.SemanticVersion.Range{394 .semver = std.SemanticVersion.Range{
282 .min = .{ .major = 12, .minor = 0, .patch = 0 },395 .min = .{ .major = 12, .minor = 0, .patch = 0 },
283 .max = .{ .major = 14, .minor = 0, .patch = 0 },396 .max = .{ .major = 14, .minor = 0, .patch = 0 },
284 },397 },
285 },398 },
286 .macos => return switch (arch) {399 .macos => switch (arch) {
287 .aarch64 => VersionRange{400 .aarch64 => VersionRange{
288 .semver = .{401 .semver = .{
289 .min = .{ .major = 11, .minor = 7, .patch = 1 },402 .min = .{ .major = 11, .minor = 7, .patch = 1 },
...@@ -298,50 +411,56 @@ pub const Os = struct {...@@ -298,50 +411,56 @@ pub const Os = struct {
298 },411 },
299 else => unreachable,412 else => unreachable,
300 },413 },
301 .ios => return .{414 .ios => .{
302 .semver = .{415 .semver = .{
303 .min = .{ .major = 12, .minor = 0, .patch = 0 },416 .min = .{ .major = 12, .minor = 0, .patch = 0 },
304 .max = .{ .major = 17, .minor = 1, .patch = 0 },417 .max = .{ .major = 17, .minor = 1, .patch = 0 },
305 },418 },
306 },419 },
307 .watchos => return .{420 .watchos => .{
308 .semver = .{421 .semver = .{
309 .min = .{ .major = 6, .minor = 0, .patch = 0 },422 .min = .{ .major = 6, .minor = 0, .patch = 0 },
310 .max = .{ .major = 10, .minor = 1, .patch = 0 },423 .max = .{ .major = 10, .minor = 1, .patch = 0 },
311 },424 },
312 },425 },
313 .tvos => return .{426 .tvos => .{
314 .semver = .{427 .semver = .{
315 .min = .{ .major = 13, .minor = 0, .patch = 0 },428 .min = .{ .major = 13, .minor = 0, .patch = 0 },
316 .max = .{ .major = 17, .minor = 1, .patch = 0 },429 .max = .{ .major = 17, .minor = 1, .patch = 0 },
317 },430 },
318 },431 },
319 .netbsd => return .{432 .netbsd => .{
320 .semver = .{433 .semver = .{
321 .min = .{ .major = 8, .minor = 0, .patch = 0 },434 .min = .{ .major = 8, .minor = 0, .patch = 0 },
322 .max = .{ .major = 10, .minor = 0, .patch = 0 },435 .max = .{ .major = 10, .minor = 0, .patch = 0 },
323 },436 },
324 },437 },
325 .openbsd => return .{438 .openbsd => .{
326 .semver = .{439 .semver = .{
327 .min = .{ .major = 6, .minor = 8, .patch = 0 },440 .min = .{ .major = 6, .minor = 8, .patch = 0 },
328 .max = .{ .major = 7, .minor = 4, .patch = 0 },441 .max = .{ .major = 7, .minor = 4, .patch = 0 },
329 },442 },
330 },443 },
331 .dragonfly => return .{444 .dragonfly => .{
332 .semver = .{445 .semver = .{
333 .min = .{ .major = 5, .minor = 8, .patch = 0 },446 .min = .{ .major = 5, .minor = 8, .patch = 0 },
334 .max = .{ .major = 6, .minor = 4, .patch = 0 },447 .max = .{ .major = 6, .minor = 4, .patch = 0 },
335 },448 },
336 },449 },
337 .solaris => return .{450 .solaris => .{
338 .semver = .{451 .semver = .{
339 .min = .{ .major = 5, .minor = 11, .patch = 0 },452 .min = .{ .major = 5, .minor = 11, .patch = 0 },
340 .max = .{ .major = 5, .minor = 11, .patch = 0 },453 .max = .{ .major = 5, .minor = 11, .patch = 0 },
341 },454 },
342 },455 },
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 => .{
345 .linux = .{464 .linux = .{
346 .range = .{465 .range = .{
347 .min = .{ .major = 4, .minor = 19, .patch = 0 },466 .min = .{ .major = 4, .minor = 19, .patch = 0 },
...@@ -351,13 +470,13 @@ pub const Os = struct {...@@ -351,13 +470,13 @@ pub const Os = struct {
351 },470 },
352 },471 },
353472
354 .windows => return .{473 .windows => .{
355 .windows = .{474 .windows = .{
356 .min = .win8_1,475 .min = .win8_1,
357 .max = WindowsVersion.latest,476 .max = WindowsVersion.latest,
358 },477 },
359 },478 },
360 }479 };
361 }480 }
362 };481 };
363482
...@@ -370,38 +489,28 @@ pub const Os = struct {...@@ -370,38 +489,28 @@ pub const Os = struct {
370489
371 /// Provides a tagged union. `Target` does not store the tag because it is490 /// Provides a tagged union. `Target` does not store the tag because it is
372 /// redundant with the OS tag; this function abstracts that part away.491 /// redundant with the OS tag; this function abstracts that part away.
373 pub inline fn getVersionRange(self: Os) TaggedVersionRange {492 pub inline fn getVersionRange(os: Os) TaggedVersionRange {
374 switch (self.tag) {493 return switch (os.tag.getVersionRangeTag()) {
375 .linux => return TaggedVersionRange{ .linux = self.version_range.linux },494 .none => .{ .none = {} },
376 .windows => return TaggedVersionRange{ .windows = self.version_range.windows },495 .semver => .{ .semver = os.version_range.semver },
377496 .linux => .{ .linux = os.version_range.linux },
378 .freebsd,497 .windows => .{ .windows = os.version_range.windows },
379 .macos,498 };
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 }
391 }499 }
392500
393 /// Checks if system is guaranteed to be at least `version` or older than `version`.501 /// Checks if system is guaranteed to be at least `version` or older than `version`.
394 /// Returns `null` if a runtime check is required.502 /// Returns `null` if a runtime check is required.
395 pub inline fn isAtLeast(self: Os, comptime tag: Tag, version: switch (tag) {503 pub inline fn isAtLeast(os: Os, comptime tag: Tag, ver: switch (tag.getVersionRangeTag()) {
396 else => std.SemanticVersion,504 .none => void,
505 .semver, .linux => std.SemanticVersion,
397 .windows => WindowsVersion,506 .windows => WindowsVersion,
398 }) ?bool {507 }) ?bool {
399 if (self.tag != tag) return false;508 return if (os.tag != tag) false else switch (tag.getVersionRangeTag()) {
400509 .none => true,
401 return switch (tag) {510 inline .semver,
402 .linux => self.version_range.linux.isAtLeast(version),511 .linux,
403 .windows => self.version_range.windows.isAtLeast(version),512 .windows,
404 else => self.version_range.semver.isAtLeast(version),513 => |field| @field(os.version_range, @tagName(field)).isAtLeast(ver),
405 };514 };
406 }515 }
407516
...@@ -528,11 +637,8 @@ pub const Abi = enum {...@@ -528,11 +637,8 @@ pub const Abi = enum {
528 mesh,637 mesh,
529 amplification,638 amplification,
530639
531 pub fn default(arch: Cpu.Arch, target_os: Os) Abi {640 pub fn default(arch: Cpu.Arch, os: Os) Abi {
532 if (arch.isWasm()) {641 return if (arch.isWasm()) .musl else switch (os.tag) {
533 return .musl;
534 }
535 switch (target_os.tag) {
536 .freestanding,642 .freestanding,
537 .ananas,643 .ananas,
538 .cloudabi,644 .cloudabi,
...@@ -554,7 +660,7 @@ pub const Abi = enum {...@@ -554,7 +660,7 @@ pub const Abi = enum {
554 .amdpal,660 .amdpal,
555 .hermit,661 .hermit,
556 .other,662 .other,
557 => return .eabi,663 => .eabi,
558 .openbsd,664 .openbsd,
559 .freebsd,665 .freebsd,
560 .fuchsia,666 .fuchsia,
...@@ -563,12 +669,12 @@ pub const Abi = enum {...@@ -563,12 +669,12 @@ pub const Abi = enum {
563 .hurd,669 .hurd,
564 .haiku,670 .haiku,
565 .windows,671 .windows,
566 => return .gnu,672 => .gnu,
567 .uefi => return .msvc,673 .uefi => .msvc,
568 .linux,674 .linux,
569 .wasi,675 .wasi,
570 .emscripten,676 .emscripten,
571 => return .musl,677 => .musl,
572 .opencl, // TODO: SPIR-V ABIs with Linkage capability678 .opencl, // TODO: SPIR-V ABIs with Linkage capability
573 .glsl450,679 .glsl450,
574 .vulkan,680 .vulkan,
...@@ -582,8 +688,8 @@ pub const Abi = enum {...@@ -582,8 +688,8 @@ pub const Abi = enum {
582 .liteos, // TODO: audit this688 .liteos, // TODO: audit this
583 .solaris,689 .solaris,
584 .illumos,690 .illumos,
585 => return .none,691 => .none,
586 }692 };
587 }693 }
588694
589 pub inline fn isGnu(abi: Abi) bool {695 pub inline fn isGnu(abi: Abi) bool {
...@@ -635,7 +741,7 @@ pub const ObjectFormat = enum {...@@ -635,7 +741,7 @@ pub const ObjectFormat = enum {
635 /// Nvidia PTX format741 /// Nvidia PTX format
636 nvptx,742 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 {
639 return switch (of) {745 return switch (of) {
640 .coff => ".obj",746 .coff => ".obj",
641 .elf, .macho, .wasm => ".o",747 .elf, .macho, .wasm => ".o",
...@@ -643,18 +749,18 @@ pub const ObjectFormat = enum {...@@ -643,18 +749,18 @@ pub const ObjectFormat = enum {
643 .spirv => ".spv",749 .spirv => ".spv",
644 .hex => ".ihex",750 .hex => ".ihex",
645 .raw => ".bin",751 .raw => ".bin",
646 .plan9 => plan9Ext(cpu_arch),752 .plan9 => arch.plan9Ext(),
647 .nvptx => ".ptx",753 .nvptx => ".ptx",
648 .dxcontainer => ".dxil",754 .dxcontainer => ".dxil",
649 };755 };
650 }756 }
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 {
653 return switch (os_tag) {759 return switch (os_tag) {
654 .windows, .uefi => .coff,760 .windows, .uefi => .coff,
655 .ios, .macos, .watchos, .tvos => .macho,761 .ios, .macos, .watchos, .tvos => .macho,
656 .plan9 => .plan9,762 .plan9 => .plan9,
657 else => return switch (cpu_arch) {763 else => switch (arch) {
658 .wasm32, .wasm64 => .wasm,764 .wasm32, .wasm64 => .wasm,
659 .spirv32, .spirv64 => .spirv,765 .spirv32, .spirv64 => .spirv,
660 .nvptx, .nvptx64 => .nvptx,766 .nvptx, .nvptx64 => .nvptx,
...@@ -725,14 +831,14 @@ pub const Cpu = struct {...@@ -725,14 +831,14 @@ pub const Cpu = struct {
725831
726 pub fn isEnabled(set: Set, arch_feature_index: Index) bool {832 pub fn isEnabled(set: Set, arch_feature_index: Index) bool {
727 const usize_index = arch_feature_index / @bitSizeOf(usize);833 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));
729 return (set.ints[usize_index] & (@as(usize, 1) << bit_index)) != 0;835 return (set.ints[usize_index] & (@as(usize, 1) << bit_index)) != 0;
730 }836 }
731837
732 /// Adds the specified feature but not its dependencies.838 /// Adds the specified feature but not its dependencies.
733 pub fn addFeature(set: *Set, arch_feature_index: Index) void {839 pub fn addFeature(set: *Set, arch_feature_index: Index) void {
734 const usize_index = arch_feature_index / @bitSizeOf(usize);840 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));
736 set.ints[usize_index] |= @as(usize, 1) << bit_index;842 set.ints[usize_index] |= @as(usize, 1) << bit_index;
737 }843 }
738844
...@@ -751,7 +857,7 @@ pub const Cpu = struct {...@@ -751,7 +857,7 @@ pub const Cpu = struct {
751 /// Removes the specified feature but not its dependents.857 /// Removes the specified feature but not its dependents.
752 pub fn removeFeature(set: *Set, arch_feature_index: Index) void {858 pub fn removeFeature(set: *Set, arch_feature_index: Index) void {
753 const usize_index = arch_feature_index / @bitSizeOf(usize);859 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));
755 set.ints[usize_index] &= ~(@as(usize, 1) << bit_index);861 set.ints[usize_index] &= ~(@as(usize, 1) << bit_index);
756 }862 }
757863
...@@ -773,7 +879,7 @@ pub const Cpu = struct {...@@ -773,7 +879,7 @@ pub const Cpu = struct {
773 var old = set.ints;879 var old = set.ints;
774 while (true) {880 while (true) {
775 for (all_features_list, 0..) |feature, index_usize| {881 for (all_features_list, 0..) |feature, index_usize| {
776 const index = @as(Index, @intCast(index_usize));882 const index: Index = @intCast(index_usize);
777 if (set.isEnabled(index)) {883 if (set.isEnabled(index)) {
778 set.addFeatureSet(feature.dependencies);884 set.addFeatureSet(feature.dependencies);
779 }885 }
...@@ -785,7 +891,7 @@ pub const Cpu = struct {...@@ -785,7 +891,7 @@ pub const Cpu = struct {
785 }891 }
786892
787 pub fn asBytes(set: *const Set) *const [byte_count]u8 {893 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];
789 }895 }
790896
791 pub fn eql(set: Set, other_set: Set) bool {897 pub fn eql(set: Set, other_set: Set) bool {
...@@ -1231,7 +1337,7 @@ pub const Cpu = struct {...@@ -1231,7 +1337,7 @@ pub const Cpu = struct {
1231 }1337 }
12321338
1233 /// Returns a name that matches the lib/std/target/* source file name.1339 /// 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 {
1235 return switch (arch) {1341 return switch (arch) {
1236 .arm, .armeb, .thumb, .thumbeb => "arm",1342 .arm, .armeb, .thumb, .thumbeb => "arm",
1237 .aarch64, .aarch64_be, .aarch64_32 => "aarch64",1343 .aarch64, .aarch64_be, .aarch64_32 => "aarch64",
...@@ -1320,6 +1426,30 @@ pub const Cpu = struct {...@@ -1320,6 +1426,30 @@ pub const Cpu = struct {
1320 const finalized = array;1426 const finalized = array;
1321 return &finalized;1427 return &finalized;
1322 }1428 }
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 }
1323 };1453 };
13241454
1325 pub const Model = struct {1455 pub const Model = struct {
...@@ -1399,112 +1529,76 @@ pub const Cpu = struct {...@@ -1399,112 +1529,76 @@ pub const Cpu = struct {
1399 }1529 }
1400};1530};
14011531
1402pub fn zigTriple(self: Target, allocator: Allocator) Allocator.Error![]u8 {1532pub fn zigTriple(target: Target, allocator: Allocator) Allocator.Error![]u8 {
1403 return Query.fromTarget(self).zigTriple(allocator);1533 return Query.fromTarget(target).zigTriple(allocator);
1404}1534}
14051535
1406pub fn linuxTripleSimple(allocator: Allocator, cpu_arch: Cpu.Arch, os_tag: Os.Tag, abi: Abi) ![]u8 {1536pub fn linuxTripleSimple(allocator: Allocator, 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) });1537 return std.fmt.allocPrint(allocator, "{s}-{s}-{s}", .{ @tagName(arch), @tagName(os_tag), @tagName(abi) });
1408}1538}
14091539
1410pub fn linuxTriple(self: Target, allocator: Allocator) ![]u8 {1540pub fn linuxTriple(target: Target, allocator: Allocator) ![]u8 {
1411 return linuxTripleSimple(allocator, self.cpu.arch, self.os.tag, self.abi);1541 return linuxTripleSimple(allocator, target.cpu.arch, target.os.tag, target.abi);
1412}1542}
14131543
1414pub fn exeFileExtSimple(cpu_arch: Cpu.Arch, os_tag: Os.Tag) [:0]const u8 {1544pub fn exeFileExt(target: Target) [:0]const u8 {
1415 return switch (os_tag) {1545 return target.os.tag.exeFileExt(target.cpu.arch);
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();
1446}1546}
14471547
1448pub fn libPrefix_os_abi(os_tag: Os.Tag, abi: Abi) [:0]const u8 {1548pub fn staticLibSuffix(target: Target) [:0]const u8 {
1449 if (abi == .msvc) {1549 return target.os.tag.staticLibSuffix(target.abi);
1450 return "";
1451 }
1452 switch (os_tag) {
1453 .windows, .uefi => return "",
1454 else => return "lib",
1455 }
1456}1550}
14571551
1458pub fn libPrefix(self: Target) [:0]const u8 {1552pub fn dynamicLibSuffix(target: Target) [:0]const u8 {
1459 return libPrefix_os_abi(self.os.tag, self.abi);1553 return target.os.tag.dynamicLibSuffix();
1460}1554}
14611555
1462pub inline fn isMinGW(self: Target) bool {1556pub fn libPrefix(target: Target) [:0]const u8 {
1463 return self.os.tag == .windows and self.isGnu();1557 return target.os.tag.libPrefix(target.abi);
1464}1558}
14651559
1466pub inline fn isGnu(self: Target) bool {1560pub inline fn isMinGW(target: Target) bool {
1467 return self.abi.isGnu();1561 return target.os.tag == .windows and target.isGnu();
1468}1562}
14691563
1470pub inline fn isMusl(self: Target) bool {1564pub inline fn isGnu(target: Target) bool {
1471 return self.abi.isMusl();1565 return target.abi.isGnu();
1472}1566}
14731567
1474pub inline fn isAndroid(self: Target) bool {1568pub inline fn isMusl(target: Target) bool {
1475 return self.abi == .android;1569 return target.abi.isMusl();
1476}1570}
14771571
1478pub inline fn isWasm(self: Target) bool {1572pub inline fn isAndroid(target: Target) bool {
1479 return self.cpu.arch.isWasm();1573 return target.abi == .android;
1480}1574}
14811575
1482pub inline fn isDarwin(self: Target) bool {1576pub inline fn isWasm(target: Target) bool {
1483 return self.os.tag.isDarwin();1577 return target.cpu.arch.isWasm();
1484}1578}
14851579
1486pub inline fn isBSD(self: Target) bool {1580pub inline fn isDarwin(target: Target) bool {
1487 return self.os.tag.isBSD();1581 return target.os.tag.isDarwin();
1488}1582}
14891583
1490pub inline fn isBpfFreestanding(self: Target) bool {1584pub inline fn isBSD(target: Target) bool {
1491 return self.cpu.arch.isBpf() and self.os.tag == .freestanding;1585 return target.os.tag.isBSD();
1492}1586}
14931587
1494pub inline fn isGnuLibC_os_tag_abi(os_tag: Os.Tag, abi: Abi) bool {1588pub inline fn isBpfFreestanding(target: Target) bool {
1495 return os_tag == .linux and abi.isGnu();1589 return target.cpu.arch.isBpf() and target.os.tag == .freestanding;
1496}1590}
14971591
1498pub inline fn isGnuLibC(self: Target) bool {1592pub inline fn isGnuLibC(target: Target) bool {
1499 return isGnuLibC_os_tag_abi(self.os.tag, self.abi);1593 return target.os.tag.isGnuLibC(target.abi);
1500}1594}
15011595
1502pub inline fn supportsNewStackCall(self: Target) bool {1596pub inline fn supportsNewStackCall(target: Target) bool {
1503 return !self.cpu.arch.isWasm();1597 return !target.cpu.arch.isWasm();
1504}1598}
15051599
1506pub inline fn isSpirV(self: Target) bool {1600pub inline fn isSpirV(target: Target) bool {
1507 return self.cpu.arch.isSpirV();1601 return target.cpu.arch.isSpirV();
1508}1602}
15091603
1510pub const FloatAbi = enum {1604pub const FloatAbi = enum {
...@@ -1512,15 +1606,15 @@ pub const FloatAbi = enum {...@@ -1512,15 +1606,15 @@ pub const FloatAbi = enum {
1512 soft,1606 soft,
1513};1607};
15141608
1515pub inline fn getFloatAbi(self: Target) FloatAbi {1609pub inline fn getFloatAbi(target: Target) FloatAbi {
1516 return self.abi.floatAbi();1610 return target.abi.floatAbi();
1517}1611}
15181612
1519pub inline fn hasDynamicLinker(self: Target) bool {1613pub inline fn hasDynamicLinker(target: Target) bool {
1520 if (self.cpu.arch.isWasm()) {1614 if (target.cpu.arch.isWasm()) {
1521 return false;1615 return false;
1522 }1616 }
1523 switch (self.os.tag) {1617 switch (target.os.tag) {
1524 .freestanding,1618 .freestanding,
1525 .ios,1619 .ios,
1526 .tvos,1620 .tvos,
...@@ -1547,259 +1641,210 @@ pub const DynamicLinker = struct {...@@ -1547,259 +1641,210 @@ pub const DynamicLinker = struct {
15471641
1548 /// Used to construct the dynamic linker path. This field should not be used1642 /// Used to construct the dynamic linker path. This field should not be used
1549 /// directly. See `get` and `set`.1643 /// directly. See `get` and `set`.
1550 max_byte: ?u8,1644 len: u8,
15511645
1552 pub const none: DynamicLinker = .{1646 pub const none: DynamicLinker = .{ .buffer = undefined, .len = 0 };
1553 .buffer = undefined,
1554 .max_byte = null,
1555 };
15561647
1557 /// Asserts that the length is less than or equal to 255 bytes.1648 /// Asserts that the length is less than or equal to 255 bytes.
1558 pub fn init(dl_or_null: ?[]const u8) DynamicLinker {1649 pub fn init(maybe_path: ?[]const u8) DynamicLinker {
1559 var result: DynamicLinker = undefined;1650 var dl: DynamicLinker = undefined;
1560 result.set(dl_or_null);1651 dl.set(maybe_path);
1561 return result;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;
1562 }1659 }
15631660
1564 /// The returned memory has the same lifetime as the `DynamicLinker`.1661 /// The returned memory has the same lifetime as the `DynamicLinker`.
1565 pub fn get(self: *const DynamicLinker) ?[]const u8 {1662 pub fn get(dl: *const DynamicLinker) ?[]const u8 {
1566 const m: usize = self.max_byte orelse return null;1663 return if (dl.len > 0) dl.buffer[0..dl.len] else null;
1567 return self.buffer[0 .. m + 1];
1568 }1664 }
15691665
1570 /// Asserts that the length is less than or equal to 255 bytes.1666 /// Asserts that the length is less than or equal to 255 bytes.
1571 pub fn set(self: *DynamicLinker, dl_or_null: ?[]const u8) void {1667 pub fn set(dl: *DynamicLinker, maybe_path: ?[]const u8) void {
1572 if (dl_or_null) |dl| {1668 const path = maybe_path orelse "";
1573 @memcpy(self.buffer[0..dl.len], dl);1669 @memcpy(dl.buffer[0..path.len], path);
1574 self.max_byte = @intCast(dl.len - 1);1670 dl.len = @intCast(path.len);
1575 } else {
1576 self.max_byte = null;
1577 }
1578 }1671 }
15791672
1580 pub fn eql(a: DynamicLinker, b: DynamicLinker) bool {1673 /// Asserts that the length is less than or equal to 255 bytes.
1581 const a_m = a.max_byte orelse return b.max_byte == null;1674 pub fn setFmt(dl: *DynamicLinker, comptime fmt_str: []const u8, args: anytype) !void {
1582 const b_m = b.max_byte orelse return false;1675 dl.len = @intCast((try std.fmt.bufPrint(&dl.buffer, fmt_str, args)).len);
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);
1587 }1676 }
1588};
15891677
1590pub fn standardDynamicLinkerPath(target: Target) DynamicLinker {1678 pub fn eql(lhs: DynamicLinker, rhs: DynamicLinker) bool {
1591 return standardDynamicLinkerPath_cpu_os_abi(target.cpu, target.os.tag, target.abi);1679 return std.mem.eql(u8, lhs.buffer[0..lhs.len], rhs.buffer[0..rhs.len]);
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});
1613 }1680 }
16141681
1615 if (abi.isMusl()) {1682 pub fn standard(cpu: Cpu, os_tag: Os.Tag, abi: Abi) DynamicLinker {
1616 const is_arm = switch (cpu.arch) {1683 return if (abi == .android) initFmt("/system/bin/linker{s}", .{
1617 .arm, .armeb, .thumb, .thumbeb => true,1684 if (ptrBitWidth_cpu_abi(cpu, abi) == 64) "64" else "",
1618 else => false,1685 }) catch unreachable else if (abi.isMusl()) return initFmt("/lib/ld-musl-{s}{s}.so.1", .{
1619 };1686 @tagName(switch (cpu.arch) {
1620 const arch_part = switch (cpu.arch) {1687 .thumb => .arm,
1621 .arm, .thumb => "arm",1688 .thumbeb => .armeb,
1622 .armeb, .thumbeb => "armeb",1689 else => cpu.arch,
1623 else => |arch| @tagName(arch),1690 }),
1624 };1691 if (cpu.arch.isArmOrThumb() and abi.floatAbi() == .hard) "hf" else "",
1625 const arch_suffix = if (is_arm and abi.floatAbi() == .hard) "hf" else "";1692 }) catch unreachable else switch (os_tag) {
1626 return print(&result, "/lib/ld-musl-{s}{s}.so.1", .{ arch_part, arch_suffix });1693 .freebsd => init("/libexec/ld-elf.so.1"),
1627 }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) {1704 .aarch64 => init("/lib/ld-linux-aarch64.so.1"),
1630 .freebsd => return copy(&result, "/libexec/ld-elf.so.1"),1705 .aarch64_be => init("/lib/ld-linux-aarch64_be.so.1"),
1631 .netbsd => return copy(&result, "/libexec/ld.elf_so"),1706 .aarch64_32 => init("/lib/ld-linux-aarch64_32.so.1"),
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"),
16401707
1641 .aarch64 => return copy(&result, "/lib/ld-linux-aarch64.so.1"),1708 .arm,
1642 .aarch64_be => return copy(&result, "/lib/ld-linux-aarch64_be.so.1"),1709 .armeb,
1643 .aarch64_32 => return copy(&result, "/lib/ld-linux-aarch64_32.so.1"),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,1717 .mips,
1646 .armeb,1718 .mipsel,
1647 .thumb,1719 .mips64,
1648 .thumbeb,1720 .mips64el,
1649 => return copy(&result, switch (abi.floatAbi()) {1721 => initFmt("/lib{s}/{s}", .{
1650 .hard => "/lib/ld-linux-armhf.so.3",1722 switch (abi) {
1651 else => "/lib/ld-linux.so.3",1723 .gnuabin32, .gnux32 => "32",
1652 }),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,1759 // TODO go over each item in this list and either move it to the above list, or
1655 .mipsel,1760 // implement the standard dynamic linker path code for it.
1656 .mips64,1761 .arc,
1657 .mips64el,1762 .csky,
1658 => {1763 .hexagon,
1659 const lib_suffix = switch (abi) {1764 .m68k,
1660 .gnuabin32, .gnux32 => "32",1765 .msp430,
1661 .gnuabi64 => "64",1766 .r600,
1662 else => "",1767 .amdgcn,
1663 };1768 .tce,
1664 const is_nan_2008 = mips.featureSetHas(cpu.features, .nan2008);1769 .tcele,
1665 const loader = if (is_nan_2008) "ld-linux-mipsn8.so.1" else "ld.so.1";1770 .xcore,
1666 return print(&result, "/lib{s}/{s}", .{ lib_suffix, loader });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,
1667 },1790 },
16681791
1669 .powerpc, .powerpcle => return copy(&result, "/lib/ld.so.1"),1792 .ios,
1670 .powerpc64, .powerpc64le => return copy(&result, "/lib64/ld64.so.2"),1793 .tvos,
1671 .s390x => return copy(&result, "/lib64/ld64.so.1"),1794 .watchos,
1672 .sparc64 => return copy(&result, "/lib64/ld-linux.so.2"),1795 .macos,
1673 .x86_64 => return copy(&result, switch (abi) {1796 => init("/usr/lib/dyld"),
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"),
16801797
1681 // Architectures in this list have been verified as not having a standard1798 // Operating systems in this list have been verified as not having a standard
1682 // dynamic linker path.1799 // dynamic linker path.
1683 .wasm32,1800 .freestanding,
1684 .wasm64,1801 .uefi,
1685 .bpfel,1802 .windows,
1686 .bpfeb,1803 .emscripten,
1687 .nvptx,1804 .wasi,
1688 .nvptx64,1805 .opencl,
1689 .spu_2,1806 .glsl450,
1690 .avr,1807 .vulkan,
1691 .spirv32,1808 .other,
1692 .spirv64,1809 .plan9,
1693 => return result,1810 => none,
1811
1812 // TODO revisit when multi-arch for Haiku is available
1813 .haiku => init("/system/runtime_loader"),
16941814
1695 // TODO go over each item in this list and either move it to the above list, or1815 // TODO go over each item in this list and either move it to the above list, or
1696 // implement the standard dynamic linker path code for it.1816 // implement the standard dynamic linker path code for it.
1697 .arc,1817 .ananas,
1698 .csky,1818 .cloudabi,
1699 .hexagon,1819 .fuchsia,
1700 .m68k,1820 .kfreebsd,
1701 .msp430,1821 .lv2,
1702 .r600,1822 .zos,
1703 .amdgcn,1823 .minix,
1704 .tce,1824 .rtems,
1705 .tcele,1825 .nacl,
1706 .xcore,1826 .aix,
1707 .le32,1827 .cuda,
1708 .le64,1828 .nvcl,
1709 .amdil,1829 .amdhsa,
1710 .amdil64,1830 .ps4,
1711 .hsail,1831 .ps5,
1712 .hsail64,1832 .elfiamcu,
1713 .spir,1833 .mesa3d,
1714 .spir64,1834 .contiki,
1715 .kalimba,1835 .amdpal,
1716 .shave,1836 .hermit,
1717 .lanai,1837 .hurd,
1718 .renderscript32,1838 .driverkit,
1719 .renderscript64,1839 .shadermodel,
1720 .ve,1840 .liteos,
1721 .dxil,1841 => none,
1722 .loongarch32,1842 };
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,
1778 }1843 }
1779}1844};
17801845
1781/// 0c spim little-endian MIPS 3000 family1846pub fn standardDynamicLinkerPath(target: Target) DynamicLinker {
1782/// 1c 68000 Motorola MC680001847 return DynamicLinker.standard(target.cpu, target.os.tag, target.abi);
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 };
1803}1848}
18041849
1805pub fn maxIntAlignment(target: Target) u16 {1850pub fn maxIntAlignment(target: Target) u16 {
...@@ -2076,7 +2121,7 @@ pub fn c_type_byte_size(t: Target, c_type: CType) u16 {...@@ -2076,7 +2121,7 @@ pub fn c_type_byte_size(t: Target, c_type: CType) u16 {
2076 16 => 2,2121 16 => 2,
2077 32 => 4,2122 32 => 4,
2078 64 => 8,2123 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))),
2080 128 => 16,2125 128 => 16,
2081 else => unreachable,2126 else => unreachable,
2082 },2127 },
...@@ -2419,7 +2464,7 @@ pub fn c_type_alignment(target: Target, c_type: CType) u16 {...@@ -2419,7 +2464,7 @@ pub fn c_type_alignment(target: Target, c_type: CType) u16 {
2419 // Next-power-of-two-aligned, up to a maximum.2464 // Next-power-of-two-aligned, up to a maximum.
2420 return @min(2465 return @min(
2421 std.math.ceilPowerOfTwoAssert(u16, (c_type_bit_size(target, c_type) + 7) / 8),2466 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) {
2423 .arm, .armeb, .thumb, .thumbeb => switch (target.os.tag) {2468 .arm, .armeb, .thumb, .thumbeb => switch (target.os.tag) {
2424 .netbsd => switch (target.abi) {2469 .netbsd => switch (target.abi) {
2425 .gnueabi,2470 .gnueabi,
...@@ -2431,7 +2476,7 @@ pub fn c_type_alignment(target: Target, c_type: CType) u16 {...@@ -2431,7 +2476,7 @@ pub fn c_type_alignment(target: Target, c_type: CType) u16 {
2431 .musleabihf,2476 .musleabihf,
2432 => 8,2477 => 8,
24332478
2434 else => @as(u16, 4),2479 else => 4,
2435 },2480 },
2436 .ios, .tvos, .watchos => 4,2481 .ios, .tvos, .watchos => 4,
2437 else => 8,2482 else => 8,
...@@ -2501,7 +2546,7 @@ pub fn c_type_alignment(target: Target, c_type: CType) u16 {...@@ -2501,7 +2546,7 @@ pub fn c_type_alignment(target: Target, c_type: CType) u16 {
2501 .wasm32,2546 .wasm32,
2502 .wasm64,2547 .wasm64,
2503 => 16,2548 => 16,
2504 },2549 }),
2505 );2550 );
2506}2551}
25072552
...@@ -2559,8 +2604,8 @@ pub fn c_type_preferred_alignment(target: Target, c_type: CType) u16 {...@@ -2559,8 +2604,8 @@ pub fn c_type_preferred_alignment(target: Target, c_type: CType) u16 {
2559 // Next-power-of-two-aligned, up to a maximum.2604 // Next-power-of-two-aligned, up to a maximum.
2560 return @min(2605 return @min(
2561 std.math.ceilPowerOfTwoAssert(u16, (c_type_bit_size(target, c_type) + 7) / 8),2606 std.math.ceilPowerOfTwoAssert(u16, (c_type_bit_size(target, c_type) + 7) / 8),
2562 switch (target.cpu.arch) {2607 @as(u16, switch (target.cpu.arch) {
2563 .msp430 => @as(u16, 2),2608 .msp430 => 2,
25642609
2565 .csky,2610 .csky,
2566 .xcore,2611 .xcore,
...@@ -2627,7 +2672,7 @@ pub fn c_type_preferred_alignment(target: Target, c_type: CType) u16 {...@@ -2627,7 +2672,7 @@ pub fn c_type_preferred_alignment(target: Target, c_type: CType) u16 {
2627 .wasm32,2672 .wasm32,
2628 .wasm64,2673 .wasm64,
2629 => 16,2674 => 16,
2630 },2675 }),
2631 );2676 );
2632}2677}
26332678
...@@ -2767,19 +2812,7 @@ fn eqlIgnoreCase(ignore_case: bool, a: []const u8, b: []const u8) bool {...@@ -2767,19 +2812,7 @@ fn eqlIgnoreCase(ignore_case: bool, a: []const u8, b: []const u8) bool {
2767}2812}
27682813
2769pub fn osArchName(target: std.Target) [:0]const u8 {2814pub fn osArchName(target: std.Target) [:0]const u8 {
2770 return switch (target.os.tag) {2815 return target.os.tag.archName(target.cpu.arch);
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 };
2783}2816}
27842817
2785const Target = @This();2818const Target = @This();
lib/std/Target/Query.zig+35-139
...@@ -124,71 +124,21 @@ pub fn fromTarget(target: Target) Query {...@@ -124,71 +124,21 @@ pub fn fromTarget(target: Target) Query {
124}124}
125125
126fn updateOsVersionRange(self: *Query, os: Target.Os) void {126fn updateOsVersionRange(self: *Query, os: Target.Os) void {
127 switch (os.tag) {127 self.os_version_min, self.os_version_max = switch (os.tag.getVersionRangeTag()) {
128 .freestanding,128 .none => .{ .{ .none = {} }, .{ .none = {} } },
129 .ananas,129 .semver => .{
130 .cloudabi,130 .{ .semver = os.version_range.semver.min },
131 .fuchsia,131 .{ .semver = os.version_range.semver.max },
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 = {} };
167 },132 },
168133 .linux => .{
169 .freebsd,134 .{ .semver = os.version_range.linux.range.min },
170 .macos,135 .{ .semver = os.version_range.linux.range.max },
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 };
185 },136 },
186137 .windows => .{
187 .windows => {138 .{ .windows = os.version_range.windows.min },
188 self.os_version_min = .{ .windows = os.version_range.windows.min };139 .{ .windows = os.version_range.windows.max },
189 self.os_version_max = .{ .windows = os.version_range.windows.max };
190 },140 },
191 }141 };
192}142}
193143
194pub const ParseOptions = struct {144pub const ParseOptions = struct {
...@@ -278,7 +228,8 @@ pub fn parse(args: ParseOptions) !Query {...@@ -278,7 +228,8 @@ pub fn parse(args: ParseOptions) !Query {
278228
279 const abi_ver_text = abi_it.rest();229 const abi_ver_text = abi_it.rest();
280 if (abi_it.next() != null) {230 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)) {
282 result.glibc_version = parseVersion(abi_ver_text) catch |err| switch (err) {233 result.glibc_version = parseVersion(abi_ver_text) catch |err| switch (err) {
283 error.Overflow => return error.InvalidAbiVersion,234 error.Overflow => return error.InvalidAbiVersion,
284 error.InvalidVersion => return error.InvalidAbiVersion,235 error.InvalidVersion => return error.InvalidAbiVersion,
...@@ -567,88 +518,33 @@ fn parseOs(result: *Query, diags: *ParseOptions.Diagnostics, text: []const u8) !...@@ -567,88 +518,33 @@ fn parseOs(result: *Query, diags: *ParseOptions.Diagnostics, text: []const u8) !
567 diags.os_tag = tag;518 diags.os_tag = tag;
568519
569 const version_text = it.rest();520 const version_text = it.rest();
570 if (it.next() == null) return;521 if (version_text.len > 0) switch (tag.getVersionRangeTag()) {
571522 .none => return error.InvalidOperatingSystemVersion,
572 switch (tag) {523 .semver, .linux => range: {
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 => {
621 var range_it = mem.splitSequence(u8, version_text, "...");524 var range_it = mem.splitSequence(u8, version_text, "...");
622525 result.os_version_min = .{
623 const min_text = range_it.next().?;526 .semver = parseVersion(range_it.first()) catch |err| switch (err) {
624 const min_ver = parseVersion(min_text) catch |err| switch (err) {527 error.Overflow => return error.InvalidOperatingSystemVersion,
625 error.Overflow => return error.InvalidOperatingSystemVersion,528 error.InvalidVersion => return error.InvalidOperatingSystemVersion,
626 error.InvalidVersion => return error.InvalidOperatingSystemVersion,529 },
627 };530 };
628 result.os_version_min = .{ .semver = min_ver };531 result.os_version_max = .{
629532 .semver = parseVersion(range_it.next() orelse break :range) catch |err| switch (err) {
630 const max_text = range_it.next() orelse return;533 error.Overflow => return error.InvalidOperatingSystemVersion,
631 const max_ver = parseVersion(max_text) catch |err| switch (err) {534 error.InvalidVersion => return error.InvalidOperatingSystemVersion,
632 error.Overflow => return error.InvalidOperatingSystemVersion,535 },
633 error.InvalidVersion => return error.InvalidOperatingSystemVersion,
634 };536 };
635 result.os_version_max = .{ .semver = max_ver };
636 },537 },
637538 .windows => range: {
638 .windows => {
639 var range_it = mem.splitSequence(u8, version_text, "...");539 var range_it = mem.splitSequence(u8, version_text, "...");
640540 result.os_version_min = .{
641 const min_text = range_it.first();541 .windows = try Target.Os.WindowsVersion.parse(range_it.first()),
642 const min_ver = std.meta.stringToEnum(Target.Os.WindowsVersion, min_text) orelse542 };
643 return error.InvalidOperatingSystemVersion;543 result.os_version_max = .{
644 result.os_version_min = .{ .windows = min_ver };544 .windows = try Target.Os.WindowsVersion.parse(range_it.next() orelse break :range),
645545 };
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 };
650 },546 },
651 }547 };
652}548}
653549
654pub fn eql(a: Query, b: Query) bool {550pub fn eql(a: Query, b: Query) bool {
lib/std/zig/system.zig+22-22
...@@ -430,9 +430,9 @@ pub fn abiAndDynamicLinkerFromFile(...@@ -430,9 +430,9 @@ pub fn abiAndDynamicLinkerFromFile(
430 query: Target.Query,430 query: Target.Query,
431) AbiAndDynamicLinkerFromFileError!Target {431) AbiAndDynamicLinkerFromFileError!Target {
432 var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 align(@alignOf(elf.Elf64_Ehdr)) = undefined;432 var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 align(@alignOf(elf.Elf64_Ehdr)) = undefined;
433 _ = try preadMin(file, &hdr_buf, 0, hdr_buf.len);433 _ = try preadAtLeast(file, &hdr_buf, 0, hdr_buf.len);
434 const hdr32 = @as(*elf.Elf32_Ehdr, @ptrCast(&hdr_buf));434 const hdr32: *elf.Elf32_Ehdr = @ptrCast(&hdr_buf);
435 const hdr64 = @as(*elf.Elf64_Ehdr, @ptrCast(&hdr_buf));435 const hdr64: *elf.Elf64_Ehdr = @ptrCast(&hdr_buf);
436 if (!mem.eql(u8, hdr32.e_ident[0..4], elf.MAGIC)) return error.InvalidElfMagic;436 if (!mem.eql(u8, hdr32.e_ident[0..4], elf.MAGIC)) return error.InvalidElfMagic;
437 const elf_endian: std.builtin.Endian = switch (hdr32.e_ident[elf.EI_DATA]) {437 const elf_endian: std.builtin.Endian = switch (hdr32.e_ident[elf.EI_DATA]) {
438 elf.ELFDATA2LSB => .little,438 elf.ELFDATA2LSB => .little,
...@@ -469,7 +469,7 @@ pub fn abiAndDynamicLinkerFromFile(...@@ -469,7 +469,7 @@ pub fn abiAndDynamicLinkerFromFile(
469 // Reserve some bytes so that we can deref the 64-bit struct fields469 // Reserve some bytes so that we can deref the 64-bit struct fields
470 // even when the ELF file is 32-bits.470 // even when the ELF file is 32-bits.
471 const ph_reserve: usize = @sizeOf(elf.Elf64_Phdr) - @sizeOf(elf.Elf32_Phdr);471 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);
473 var ph_buf_i: usize = 0;473 var ph_buf_i: usize = 0;
474 while (ph_buf_i < ph_read_byte_len and ph_i < phnum) : ({474 while (ph_buf_i < ph_read_byte_len and ph_i < phnum) : ({
475 ph_i += 1;475 ph_i += 1;
...@@ -484,13 +484,13 @@ pub fn abiAndDynamicLinkerFromFile(...@@ -484,13 +484,13 @@ pub fn abiAndDynamicLinkerFromFile(
484 const p_offset = elfInt(is_64, need_bswap, ph32.p_offset, ph64.p_offset);484 const p_offset = elfInt(is_64, need_bswap, ph32.p_offset, ph64.p_offset);
485 const p_filesz = elfInt(is_64, need_bswap, ph32.p_filesz, ph64.p_filesz);485 const p_filesz = elfInt(is_64, need_bswap, ph32.p_filesz, ph64.p_filesz);
486 if (p_filesz > result.dynamic_linker.buffer.len) return error.NameTooLong;486 if (p_filesz > result.dynamic_linker.buffer.len) return error.NameTooLong;
487 const filesz = @as(usize, @intCast(p_filesz));487 const filesz: usize = @intCast(p_filesz);
488 _ = try preadMin(file, result.dynamic_linker.buffer[0..filesz], p_offset, filesz);488 _ = try preadAtLeast(file, result.dynamic_linker.buffer[0..filesz], p_offset, filesz);
489 // PT_INTERP includes a null byte in filesz.489 // PT_INTERP includes a null byte in filesz.
490 const len = filesz - 1;490 const len = filesz - 1;
491 // dynamic_linker.max_byte is "max", not "len".491 // dynamic_linker.max_byte is "max", not "len".
492 // We know it will fit in u8 because we check against dynamic_linker.buffer.len above.492 // 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
495 // Use it to determine ABI.495 // Use it to determine ABI.
496 const full_ld_path = result.dynamic_linker.buffer[0..len];496 const full_ld_path = result.dynamic_linker.buffer[0..len];
...@@ -516,7 +516,7 @@ pub fn abiAndDynamicLinkerFromFile(...@@ -516,7 +516,7 @@ pub fn abiAndDynamicLinkerFromFile(
516 // Reserve some bytes so that we can deref the 64-bit struct fields516 // Reserve some bytes so that we can deref the 64-bit struct fields
517 // even when the ELF file is 32-bits.517 // even when the ELF file is 32-bits.
518 const dyn_reserve: usize = @sizeOf(elf.Elf64_Dyn) - @sizeOf(elf.Elf32_Dyn);518 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(
520 file,520 file,
521 dyn_buf[0 .. dyn_buf.len - dyn_reserve],521 dyn_buf[0 .. dyn_buf.len - dyn_reserve],
522 dyn_off,522 dyn_off,
...@@ -556,14 +556,14 @@ pub fn abiAndDynamicLinkerFromFile(...@@ -556,14 +556,14 @@ pub fn abiAndDynamicLinkerFromFile(
556 var sh_buf: [16 * @sizeOf(elf.Elf64_Shdr)]u8 align(@alignOf(elf.Elf64_Shdr)) = undefined;556 var sh_buf: [16 * @sizeOf(elf.Elf64_Shdr)]u8 align(@alignOf(elf.Elf64_Shdr)) = undefined;
557 if (sh_buf.len < shentsize) return error.InvalidElfFile;557 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);
560 const shstr32: *elf.Elf32_Shdr = @ptrCast(@alignCast(&sh_buf));560 const shstr32: *elf.Elf32_Shdr = @ptrCast(@alignCast(&sh_buf));
561 const shstr64: *elf.Elf64_Shdr = @ptrCast(@alignCast(&sh_buf));561 const shstr64: *elf.Elf64_Shdr = @ptrCast(@alignCast(&sh_buf));
562 const shstrtab_off = elfInt(is_64, need_bswap, shstr32.sh_offset, shstr64.sh_offset);562 const shstrtab_off = elfInt(is_64, need_bswap, shstr32.sh_offset, shstr64.sh_offset);
563 const shstrtab_size = elfInt(is_64, need_bswap, shstr32.sh_size, shstr64.sh_size);563 const shstrtab_size = elfInt(is_64, need_bswap, shstr32.sh_size, shstr64.sh_size);
564 var strtab_buf: [4096:0]u8 = undefined;564 var strtab_buf: [4096:0]u8 = undefined;
565 const shstrtab_len = @min(shstrtab_size, strtab_buf.len);565 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);
567 const shstrtab = strtab_buf[0..shstrtab_read_len];567 const shstrtab = strtab_buf[0..shstrtab_read_len];
568568
569 const shnum = elfInt(is_64, need_bswap, hdr32.e_shnum, hdr64.e_shnum);569 const shnum = elfInt(is_64, need_bswap, hdr32.e_shnum, hdr64.e_shnum);
...@@ -572,7 +572,7 @@ pub fn abiAndDynamicLinkerFromFile(...@@ -572,7 +572,7 @@ pub fn abiAndDynamicLinkerFromFile(
572 // Reserve some bytes so that we can deref the 64-bit struct fields572 // Reserve some bytes so that we can deref the 64-bit struct fields
573 // even when the ELF file is 32-bits.573 // even when the ELF file is 32-bits.
574 const sh_reserve: usize = @sizeOf(elf.Elf64_Shdr) - @sizeOf(elf.Elf32_Shdr);574 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(
576 file,576 file,
577 sh_buf[0 .. sh_buf.len - sh_reserve],577 sh_buf[0 .. sh_buf.len - sh_reserve],
578 shoff,578 shoff,
...@@ -604,7 +604,7 @@ pub fn abiAndDynamicLinkerFromFile(...@@ -604,7 +604,7 @@ pub fn abiAndDynamicLinkerFromFile(
604 const rp_max_size = ds.size - rpoff;604 const rp_max_size = ds.size - rpoff;
605605
606 const strtab_len = @min(rp_max_size, strtab_buf.len);606 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);
608 const strtab = strtab_buf[0..strtab_read_len];608 const strtab = strtab_buf[0..strtab_read_len];
609609
610 const rpath_list = mem.sliceTo(strtab, 0);610 const rpath_list = mem.sliceTo(strtab, 0);
...@@ -814,9 +814,9 @@ fn glibcVerFromRPath(rpath: []const u8) !std.SemanticVersion {...@@ -814,9 +814,9 @@ fn glibcVerFromRPath(rpath: []const u8) !std.SemanticVersion {
814814
815fn glibcVerFromSoFile(file: fs.File) !std.SemanticVersion {815fn glibcVerFromSoFile(file: fs.File) !std.SemanticVersion {
816 var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 align(@alignOf(elf.Elf64_Ehdr)) = undefined;816 var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 align(@alignOf(elf.Elf64_Ehdr)) = undefined;
817 _ = try preadMin(file, &hdr_buf, 0, hdr_buf.len);817 _ = try preadAtLeast(file, &hdr_buf, 0, hdr_buf.len);
818 const hdr32 = @as(*elf.Elf32_Ehdr, @ptrCast(&hdr_buf));818 const hdr32: *elf.Elf32_Ehdr = @ptrCast(&hdr_buf);
819 const hdr64 = @as(*elf.Elf64_Ehdr, @ptrCast(&hdr_buf));819 const hdr64: *elf.Elf64_Ehdr = @ptrCast(&hdr_buf);
820 if (!mem.eql(u8, hdr32.e_ident[0..4], elf.MAGIC)) return error.InvalidElfMagic;820 if (!mem.eql(u8, hdr32.e_ident[0..4], elf.MAGIC)) return error.InvalidElfMagic;
821 const elf_endian: std.builtin.Endian = switch (hdr32.e_ident[elf.EI_DATA]) {821 const elf_endian: std.builtin.Endian = switch (hdr32.e_ident[elf.EI_DATA]) {
822 elf.ELFDATA2LSB => .little,822 elf.ELFDATA2LSB => .little,
...@@ -838,14 +838,14 @@ fn glibcVerFromSoFile(file: fs.File) !std.SemanticVersion {...@@ -838,14 +838,14 @@ fn glibcVerFromSoFile(file: fs.File) !std.SemanticVersion {
838 var sh_buf: [16 * @sizeOf(elf.Elf64_Shdr)]u8 align(@alignOf(elf.Elf64_Shdr)) = undefined;838 var sh_buf: [16 * @sizeOf(elf.Elf64_Shdr)]u8 align(@alignOf(elf.Elf64_Shdr)) = undefined;
839 if (sh_buf.len < shentsize) return error.InvalidElfFile;839 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);
842 const shstr32: *elf.Elf32_Shdr = @ptrCast(@alignCast(&sh_buf));842 const shstr32: *elf.Elf32_Shdr = @ptrCast(@alignCast(&sh_buf));
843 const shstr64: *elf.Elf64_Shdr = @ptrCast(@alignCast(&sh_buf));843 const shstr64: *elf.Elf64_Shdr = @ptrCast(@alignCast(&sh_buf));
844 const shstrtab_off = elfInt(is_64, need_bswap, shstr32.sh_offset, shstr64.sh_offset);844 const shstrtab_off = elfInt(is_64, need_bswap, shstr32.sh_offset, shstr64.sh_offset);
845 const shstrtab_size = elfInt(is_64, need_bswap, shstr32.sh_size, shstr64.sh_size);845 const shstrtab_size = elfInt(is_64, need_bswap, shstr32.sh_size, shstr64.sh_size);
846 var strtab_buf: [4096:0]u8 = undefined;846 var strtab_buf: [4096:0]u8 = undefined;
847 const shstrtab_len = @min(shstrtab_size, strtab_buf.len);847 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);
849 const shstrtab = strtab_buf[0..shstrtab_read_len];849 const shstrtab = strtab_buf[0..shstrtab_read_len];
850 const shnum = elfInt(is_64, need_bswap, hdr32.e_shnum, hdr64.e_shnum);850 const shnum = elfInt(is_64, need_bswap, hdr32.e_shnum, hdr64.e_shnum);
851 var sh_i: u16 = 0;851 var sh_i: u16 = 0;
...@@ -853,7 +853,7 @@ fn glibcVerFromSoFile(file: fs.File) !std.SemanticVersion {...@@ -853,7 +853,7 @@ fn glibcVerFromSoFile(file: fs.File) !std.SemanticVersion {
853 // Reserve some bytes so that we can deref the 64-bit struct fields853 // Reserve some bytes so that we can deref the 64-bit struct fields
854 // even when the ELF file is 32-bits.854 // even when the ELF file is 32-bits.
855 const sh_reserve: usize = @sizeOf(elf.Elf64_Shdr) - @sizeOf(elf.Elf32_Shdr);855 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(
857 file,857 file,
858 sh_buf[0 .. sh_buf.len - sh_reserve],858 sh_buf[0 .. sh_buf.len - sh_reserve],
859 shoff,859 shoff,
...@@ -890,7 +890,7 @@ fn glibcVerFromSoFile(file: fs.File) !std.SemanticVersion {...@@ -890,7 +890,7 @@ fn glibcVerFromSoFile(file: fs.File) !std.SemanticVersion {
890890
891 const dynstr_size: usize = @intCast(dynstr.size);891 const dynstr_size: usize = @intCast(dynstr.size);
892 const dynstr_bytes = buf[0..dynstr_size];892 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);
894 var it = mem.splitScalar(u8, dynstr_bytes, 0);894 var it = mem.splitScalar(u8, dynstr_bytes, 0);
895 var max_ver: std.SemanticVersion = .{ .major = 2, .minor = 2, .patch = 5 };895 var max_ver: std.SemanticVersion = .{ .major = 2, .minor = 2, .patch = 5 };
896 while (it.next()) |s| {896 while (it.next()) |s| {
...@@ -1029,7 +1029,7 @@ fn detectAbiAndDynamicLinker(...@@ -1029,7 +1029,7 @@ fn detectAbiAndDynamicLinker(
1029 };1029 };
1030 errdefer file.close();1030 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) {
1033 error.UnexpectedEndOfFile,1033 error.UnexpectedEndOfFile,
1034 error.UnableToReadElfFile,1034 error.UnableToReadElfFile,
1035 => break :blk file,1035 => break :blk file,
...@@ -1083,7 +1083,7 @@ fn defaultAbiAndDynamicLinker(cpu: Target.Cpu, os: Target.Os, query: Target.Quer...@@ -1083,7 +1083,7 @@ fn defaultAbiAndDynamicLinker(cpu: Target.Cpu, os: Target.Os, query: Target.Quer
1083 .abi = abi,1083 .abi = abi,
1084 .ofmt = query.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch),1084 .ofmt = query.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch),
1085 .dynamic_linker = if (query.dynamic_linker.get() == null)1085 .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)
1087 else1087 else
1088 query.dynamic_linker,1088 query.dynamic_linker,
1089 };1089 };
...@@ -1094,7 +1094,7 @@ const LdInfo = struct {...@@ -1094,7 +1094,7 @@ const LdInfo = struct {
1094 abi: Target.Abi,1094 abi: Target.Abi,
1095};1095};
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 {
1098 var i: usize = 0;1098 var i: usize = 0;
1099 while (i < min_read_len) {1099 while (i < min_read_len) {
1100 const len = file.pread(buf[i..], offset + i) catch |err| switch (err) {1100 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 {...@@ -140,13 +140,11 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
140 }),140 }),
141 .windows => |windows| try buffer.writer().print(141 .windows => |windows| try buffer.writer().print(
142 \\ .windows = .{{142 \\ .windows = .{{
143 \\ .min = {s},143 \\ .min = {c},
144 \\ .max = {s},144 \\ .max = {c},
145 \\ }}}},145 \\ }}}},
146 \\146 \\
147 ,147 , .{ windows.min, windows.max }),
148 .{ windows.min, windows.max },
149 ),
150 }148 }
151 try buffer.appendSlice(149 try buffer.appendSlice(
152 \\};150 \\};