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

Target: cleanup


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

lib/std/Target.zig+450-422
...@@ -81,14 +81,48 @@ pub const Os = struct {...@@ -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 .wasi,
161 .emscripten,
162 .driverkit,
163 .shadermodel,
164 .liteos,
165 .uefi,
166 .opencl, // TODO: OpenCL versions
167 .glsl450, // TODO: GLSL versions
168 .vulkan,
169 .plan9,
170 .illumos,
171 .other,
172 => .none,
173
174 .freebsd,
175 .macos,
176 .ios,
177 .tvos,
178 .watchos,
179 .netbsd,
180 .openbsd,
181 .dragonfly,
182 .solaris,
183 => .semver,
184
185 .linux => .linux,
186
187 .windows => .windows,
188 };
189 }
190
191 pub fn archName(tag: Tag, arch: Cpu.Arch) [:0]const u8 {
192 return switch (tag) {
193 .linux => switch (arch) {
194 .arm, .armeb, .thumb, .thumbeb => "arm",
195 .aarch64, .aarch64_be, .aarch64_32 => "aarch64",
196 .mips, .mipsel, .mips64, .mips64el => "mips",
197 .powerpc, .powerpcle, .powerpc64, .powerpc64le => "powerpc",
198 .riscv32, .riscv64 => "riscv",
199 .sparc, .sparcel, .sparc64 => "sparc",
200 .x86, .x86_64 => "x86",
201 else => @tagName(arch),
202 },
203 else => @tagName(arch),
204 };
205 }
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,
...@@ -275,15 +389,15 @@ pub const Os = struct {...@@ -275,15 +389,15 @@ pub const Os = struct {
275 .plan9,389 .plan9,
276 .illumos,390 .illumos,
277 .other,391 .other,
278 => return .{ .none = {} },392 => .{ .none = {} },
279393
280 .freebsd => return .{394 .freebsd => .{
281 .semver = std.SemanticVersion.Range{395 .semver = std.SemanticVersion.Range{
282 .min = .{ .major = 12, .minor = 0, .patch = 0 },396 .min = .{ .major = 12, .minor = 0, .patch = 0 },
283 .max = .{ .major = 14, .minor = 0, .patch = 0 },397 .max = .{ .major = 14, .minor = 0, .patch = 0 },
284 },398 },
285 },399 },
286 .macos => return switch (arch) {400 .macos => switch (arch) {
287 .aarch64 => VersionRange{401 .aarch64 => VersionRange{
288 .semver = .{402 .semver = .{
289 .min = .{ .major = 11, .minor = 7, .patch = 1 },403 .min = .{ .major = 11, .minor = 7, .patch = 1 },
...@@ -298,50 +412,50 @@ pub const Os = struct {...@@ -298,50 +412,50 @@ pub const Os = struct {
298 },412 },
299 else => unreachable,413 else => unreachable,
300 },414 },
301 .ios => return .{415 .ios => .{
302 .semver = .{416 .semver = .{
303 .min = .{ .major = 12, .minor = 0, .patch = 0 },417 .min = .{ .major = 12, .minor = 0, .patch = 0 },
304 .max = .{ .major = 17, .minor = 1, .patch = 0 },418 .max = .{ .major = 17, .minor = 1, .patch = 0 },
305 },419 },
306 },420 },
307 .watchos => return .{421 .watchos => .{
308 .semver = .{422 .semver = .{
309 .min = .{ .major = 6, .minor = 0, .patch = 0 },423 .min = .{ .major = 6, .minor = 0, .patch = 0 },
310 .max = .{ .major = 10, .minor = 1, .patch = 0 },424 .max = .{ .major = 10, .minor = 1, .patch = 0 },
311 },425 },
312 },426 },
313 .tvos => return .{427 .tvos => .{
314 .semver = .{428 .semver = .{
315 .min = .{ .major = 13, .minor = 0, .patch = 0 },429 .min = .{ .major = 13, .minor = 0, .patch = 0 },
316 .max = .{ .major = 17, .minor = 1, .patch = 0 },430 .max = .{ .major = 17, .minor = 1, .patch = 0 },
317 },431 },
318 },432 },
319 .netbsd => return .{433 .netbsd => .{
320 .semver = .{434 .semver = .{
321 .min = .{ .major = 8, .minor = 0, .patch = 0 },435 .min = .{ .major = 8, .minor = 0, .patch = 0 },
322 .max = .{ .major = 10, .minor = 0, .patch = 0 },436 .max = .{ .major = 10, .minor = 0, .patch = 0 },
323 },437 },
324 },438 },
325 .openbsd => return .{439 .openbsd => .{
326 .semver = .{440 .semver = .{
327 .min = .{ .major = 6, .minor = 8, .patch = 0 },441 .min = .{ .major = 6, .minor = 8, .patch = 0 },
328 .max = .{ .major = 7, .minor = 4, .patch = 0 },442 .max = .{ .major = 7, .minor = 4, .patch = 0 },
329 },443 },
330 },444 },
331 .dragonfly => return .{445 .dragonfly => .{
332 .semver = .{446 .semver = .{
333 .min = .{ .major = 5, .minor = 8, .patch = 0 },447 .min = .{ .major = 5, .minor = 8, .patch = 0 },
334 .max = .{ .major = 6, .minor = 4, .patch = 0 },448 .max = .{ .major = 6, .minor = 4, .patch = 0 },
335 },449 },
336 },450 },
337 .solaris => return .{451 .solaris => .{
338 .semver = .{452 .semver = .{
339 .min = .{ .major = 5, .minor = 11, .patch = 0 },453 .min = .{ .major = 5, .minor = 11, .patch = 0 },
340 .max = .{ .major = 5, .minor = 11, .patch = 0 },454 .max = .{ .major = 5, .minor = 11, .patch = 0 },
341 },455 },
342 },456 },
343457
344 .linux => return .{458 .linux => .{
345 .linux = .{459 .linux = .{
346 .range = .{460 .range = .{
347 .min = .{ .major = 4, .minor = 19, .patch = 0 },461 .min = .{ .major = 4, .minor = 19, .patch = 0 },
...@@ -351,13 +465,13 @@ pub const Os = struct {...@@ -351,13 +465,13 @@ pub const Os = struct {
351 },465 },
352 },466 },
353467
354 .windows => return .{468 .windows => .{
355 .windows = .{469 .windows = .{
356 .min = .win8_1,470 .min = .win8_1,
357 .max = WindowsVersion.latest,471 .max = WindowsVersion.latest,
358 },472 },
359 },473 },
360 }474 };
361 }475 }
362 };476 };
363477
...@@ -370,38 +484,28 @@ pub const Os = struct {...@@ -370,38 +484,28 @@ pub const Os = struct {
370484
371 /// Provides a tagged union. `Target` does not store the tag because it is485 /// 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.486 /// redundant with the OS tag; this function abstracts that part away.
373 pub inline fn getVersionRange(self: Os) TaggedVersionRange {487 pub inline fn getVersionRange(os: Os) TaggedVersionRange {
374 switch (self.tag) {488 return switch (os.tag.getVersionRangeTag()) {
375 .linux => return TaggedVersionRange{ .linux = self.version_range.linux },489 .none => .{ .none = {} },
376 .windows => return TaggedVersionRange{ .windows = self.version_range.windows },490 .semver => .{ .semver = os.version_range.semver },
377491 .linux => .{ .linux = os.version_range.linux },
378 .freebsd,492 .windows => .{ .windows = os.version_range.windows },
379 .macos,493 };
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 }494 }
392495
393 /// Checks if system is guaranteed to be at least `version` or older than `version`.496 /// Checks if system is guaranteed to be at least `version` or older than `version`.
394 /// Returns `null` if a runtime check is required.497 /// Returns `null` if a runtime check is required.
395 pub inline fn isAtLeast(self: Os, comptime tag: Tag, version: switch (tag) {498 pub inline fn isAtLeast(os: Os, comptime tag: Tag, ver: switch (tag.getVersionRangeTag()) {
396 else => std.SemanticVersion,499 .none => void,
500 .semver, .linux => std.SemanticVersion,
397 .windows => WindowsVersion,501 .windows => WindowsVersion,
398 }) ?bool {502 }) ?bool {
399 if (self.tag != tag) return false;503 return if (os.tag != tag) false else switch (tag.getVersionRangeTag()) {
400504 .none => true,
401 return switch (tag) {505 inline .semver,
402 .linux => self.version_range.linux.isAtLeast(version),506 .linux,
403 .windows => self.version_range.windows.isAtLeast(version),507 .windows,
404 else => self.version_range.semver.isAtLeast(version),508 => |field| @field(os.version_range, @tagName(field)).isAtLeast(ver),
405 };509 };
406 }510 }
407511
...@@ -528,11 +632,8 @@ pub const Abi = enum {...@@ -528,11 +632,8 @@ pub const Abi = enum {
528 mesh,632 mesh,
529 amplification,633 amplification,
530634
531 pub fn default(arch: Cpu.Arch, target_os: Os) Abi {635 pub fn default(arch: Cpu.Arch, os: Os) Abi {
532 if (arch.isWasm()) {636 return if (arch.isWasm()) .musl else switch (os.tag) {
533 return .musl;
534 }
535 switch (target_os.tag) {
536 .freestanding,637 .freestanding,
537 .ananas,638 .ananas,
538 .cloudabi,639 .cloudabi,
...@@ -554,7 +655,7 @@ pub const Abi = enum {...@@ -554,7 +655,7 @@ pub const Abi = enum {
554 .amdpal,655 .amdpal,
555 .hermit,656 .hermit,
556 .other,657 .other,
557 => return .eabi,658 => .eabi,
558 .openbsd,659 .openbsd,
559 .freebsd,660 .freebsd,
560 .fuchsia,661 .fuchsia,
...@@ -563,12 +664,12 @@ pub const Abi = enum {...@@ -563,12 +664,12 @@ pub const Abi = enum {
563 .hurd,664 .hurd,
564 .haiku,665 .haiku,
565 .windows,666 .windows,
566 => return .gnu,667 => .gnu,
567 .uefi => return .msvc,668 .uefi => .msvc,
568 .linux,669 .linux,
569 .wasi,670 .wasi,
570 .emscripten,671 .emscripten,
571 => return .musl,672 => .musl,
572 .opencl, // TODO: SPIR-V ABIs with Linkage capability673 .opencl, // TODO: SPIR-V ABIs with Linkage capability
573 .glsl450,674 .glsl450,
574 .vulkan,675 .vulkan,
...@@ -582,8 +683,8 @@ pub const Abi = enum {...@@ -582,8 +683,8 @@ pub const Abi = enum {
582 .liteos, // TODO: audit this683 .liteos, // TODO: audit this
583 .solaris,684 .solaris,
584 .illumos,685 .illumos,
585 => return .none,686 => .none,
586 }687 };
587 }688 }
588689
589 pub inline fn isGnu(abi: Abi) bool {690 pub inline fn isGnu(abi: Abi) bool {
...@@ -635,7 +736,7 @@ pub const ObjectFormat = enum {...@@ -635,7 +736,7 @@ pub const ObjectFormat = enum {
635 /// Nvidia PTX format736 /// Nvidia PTX format
636 nvptx,737 nvptx,
637738
638 pub fn fileExt(of: ObjectFormat, cpu_arch: Cpu.Arch) [:0]const u8 {739 pub fn fileExt(of: ObjectFormat, arch: Cpu.Arch) [:0]const u8 {
639 return switch (of) {740 return switch (of) {
640 .coff => ".obj",741 .coff => ".obj",
641 .elf, .macho, .wasm => ".o",742 .elf, .macho, .wasm => ".o",
...@@ -643,18 +744,18 @@ pub const ObjectFormat = enum {...@@ -643,18 +744,18 @@ pub const ObjectFormat = enum {
643 .spirv => ".spv",744 .spirv => ".spv",
644 .hex => ".ihex",745 .hex => ".ihex",
645 .raw => ".bin",746 .raw => ".bin",
646 .plan9 => plan9Ext(cpu_arch),747 .plan9 => arch.plan9Ext(),
647 .nvptx => ".ptx",748 .nvptx => ".ptx",
648 .dxcontainer => ".dxil",749 .dxcontainer => ".dxil",
649 };750 };
650 }751 }
651752
652 pub fn default(os_tag: Os.Tag, cpu_arch: Cpu.Arch) ObjectFormat {753 pub fn default(os_tag: Os.Tag, arch: Cpu.Arch) ObjectFormat {
653 return switch (os_tag) {754 return switch (os_tag) {
654 .windows, .uefi => .coff,755 .windows, .uefi => .coff,
655 .ios, .macos, .watchos, .tvos => .macho,756 .ios, .macos, .watchos, .tvos => .macho,
656 .plan9 => .plan9,757 .plan9 => .plan9,
657 else => return switch (cpu_arch) {758 else => switch (arch) {
658 .wasm32, .wasm64 => .wasm,759 .wasm32, .wasm64 => .wasm,
659 .spirv32, .spirv64 => .spirv,760 .spirv32, .spirv64 => .spirv,
660 .nvptx, .nvptx64 => .nvptx,761 .nvptx, .nvptx64 => .nvptx,
...@@ -725,14 +826,14 @@ pub const Cpu = struct {...@@ -725,14 +826,14 @@ pub const Cpu = struct {
725826
726 pub fn isEnabled(set: Set, arch_feature_index: Index) bool {827 pub fn isEnabled(set: Set, arch_feature_index: Index) bool {
727 const usize_index = arch_feature_index / @bitSizeOf(usize);828 const usize_index = arch_feature_index / @bitSizeOf(usize);
728 const bit_index = @as(ShiftInt, @intCast(arch_feature_index % @bitSizeOf(usize)));829 const bit_index: ShiftInt = @intCast(arch_feature_index % @bitSizeOf(usize));
729 return (set.ints[usize_index] & (@as(usize, 1) << bit_index)) != 0;830 return (set.ints[usize_index] & (@as(usize, 1) << bit_index)) != 0;
730 }831 }
731832
732 /// Adds the specified feature but not its dependencies.833 /// Adds the specified feature but not its dependencies.
733 pub fn addFeature(set: *Set, arch_feature_index: Index) void {834 pub fn addFeature(set: *Set, arch_feature_index: Index) void {
734 const usize_index = arch_feature_index / @bitSizeOf(usize);835 const usize_index = arch_feature_index / @bitSizeOf(usize);
735 const bit_index = @as(ShiftInt, @intCast(arch_feature_index % @bitSizeOf(usize)));836 const bit_index: ShiftInt = @intCast(arch_feature_index % @bitSizeOf(usize));
736 set.ints[usize_index] |= @as(usize, 1) << bit_index;837 set.ints[usize_index] |= @as(usize, 1) << bit_index;
737 }838 }
738839
...@@ -751,7 +852,7 @@ pub const Cpu = struct {...@@ -751,7 +852,7 @@ pub const Cpu = struct {
751 /// Removes the specified feature but not its dependents.852 /// Removes the specified feature but not its dependents.
752 pub fn removeFeature(set: *Set, arch_feature_index: Index) void {853 pub fn removeFeature(set: *Set, arch_feature_index: Index) void {
753 const usize_index = arch_feature_index / @bitSizeOf(usize);854 const usize_index = arch_feature_index / @bitSizeOf(usize);
754 const bit_index = @as(ShiftInt, @intCast(arch_feature_index % @bitSizeOf(usize)));855 const bit_index: ShiftInt = @intCast(arch_feature_index % @bitSizeOf(usize));
755 set.ints[usize_index] &= ~(@as(usize, 1) << bit_index);856 set.ints[usize_index] &= ~(@as(usize, 1) << bit_index);
756 }857 }
757858
...@@ -773,7 +874,7 @@ pub const Cpu = struct {...@@ -773,7 +874,7 @@ pub const Cpu = struct {
773 var old = set.ints;874 var old = set.ints;
774 while (true) {875 while (true) {
775 for (all_features_list, 0..) |feature, index_usize| {876 for (all_features_list, 0..) |feature, index_usize| {
776 const index = @as(Index, @intCast(index_usize));877 const index: Index = @intCast(index_usize);
777 if (set.isEnabled(index)) {878 if (set.isEnabled(index)) {
778 set.addFeatureSet(feature.dependencies);879 set.addFeatureSet(feature.dependencies);
779 }880 }
...@@ -785,7 +886,7 @@ pub const Cpu = struct {...@@ -785,7 +886,7 @@ pub const Cpu = struct {
785 }886 }
786887
787 pub fn asBytes(set: *const Set) *const [byte_count]u8 {888 pub fn asBytes(set: *const Set) *const [byte_count]u8 {
788 return @as(*const [byte_count]u8, @ptrCast(&set.ints));889 return std.mem.sliceAsBytes(&set.ints)[0..byte_count];
789 }890 }
790891
791 pub fn eql(set: Set, other_set: Set) bool {892 pub fn eql(set: Set, other_set: Set) bool {
...@@ -1231,7 +1332,7 @@ pub const Cpu = struct {...@@ -1231,7 +1332,7 @@ pub const Cpu = struct {
1231 }1332 }
12321333
1233 /// Returns a name that matches the lib/std/target/* source file name.1334 /// Returns a name that matches the lib/std/target/* source file name.
1234 pub fn genericName(arch: Arch) []const u8 {1335 pub fn genericName(arch: Arch) [:0]const u8 {
1235 return switch (arch) {1336 return switch (arch) {
1236 .arm, .armeb, .thumb, .thumbeb => "arm",1337 .arm, .armeb, .thumb, .thumbeb => "arm",
1237 .aarch64, .aarch64_be, .aarch64_32 => "aarch64",1338 .aarch64, .aarch64_be, .aarch64_32 => "aarch64",
...@@ -1320,6 +1421,30 @@ pub const Cpu = struct {...@@ -1320,6 +1421,30 @@ pub const Cpu = struct {
1320 const finalized = array;1421 const finalized = array;
1321 return &finalized;1422 return &finalized;
1322 }1423 }
1424
1425 /// 0c spim little-endian MIPS 3000 family
1426 /// 1c 68000 Motorola MC68000
1427 /// 2c 68020 Motorola MC68020
1428 /// 5c arm little-endian ARM
1429 /// 6c amd64 AMD64 and compatibles (e.g., Intel EM64T)
1430 /// 7c arm64 ARM64 (ARMv8)
1431 /// 8c 386 Intel x86, i486, Pentium, etc.
1432 /// kc sparc Sun SPARC
1433 /// qc power Power PC
1434 /// vc mips big-endian MIPS 3000 family
1435 pub fn plan9Ext(arch: Cpu.Arch) [:0]const u8 {
1436 return switch (arch) {
1437 .arm => ".5",
1438 .x86_64 => ".6",
1439 .aarch64 => ".7",
1440 .x86 => ".8",
1441 .sparc => ".k",
1442 .powerpc, .powerpcle => ".q",
1443 .mips, .mipsel => ".v",
1444 // ISAs without designated characters get 'X' for lack of a better option.
1445 else => ".X",
1446 };
1447 }
1323 };1448 };
13241449
1325 pub const Model = struct {1450 pub const Model = struct {
...@@ -1399,112 +1524,76 @@ pub const Cpu = struct {...@@ -1399,112 +1524,76 @@ pub const Cpu = struct {
1399 }1524 }
1400};1525};
14011526
1402pub fn zigTriple(self: Target, allocator: Allocator) Allocator.Error![]u8 {1527pub fn zigTriple(target: Target, allocator: Allocator) Allocator.Error![]u8 {
1403 return Query.fromTarget(self).zigTriple(allocator);1528 return Query.fromTarget(target).zigTriple(allocator);
1404}
1405
1406pub fn linuxTripleSimple(allocator: Allocator, cpu_arch: Cpu.Arch, os_tag: Os.Tag, abi: Abi) ![]u8 {
1407 return std.fmt.allocPrint(allocator, "{s}-{s}-{s}", .{ @tagName(cpu_arch), @tagName(os_tag), @tagName(abi) });
1408}
1409
1410pub fn linuxTriple(self: Target, allocator: Allocator) ![]u8 {
1411 return linuxTripleSimple(allocator, self.cpu.arch, self.os.tag, self.abi);
1412}1529}
14131530
1414pub fn exeFileExtSimple(cpu_arch: Cpu.Arch, os_tag: Os.Tag) [:0]const u8 {1531pub fn linuxTripleSimple(allocator: Allocator, arch: Cpu.Arch, os_tag: Os.Tag, abi: Abi) ![]u8 {
1415 return switch (os_tag) {1532 return std.fmt.allocPrint(allocator, "{s}-{s}-{s}", .{ @tagName(arch), @tagName(os_tag), @tagName(abi) });
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}1533}
14391534
1440pub fn staticLibSuffix(self: Target) [:0]const u8 {1535pub fn linuxTriple(target: Target, allocator: Allocator) ![]u8 {
1441 return staticLibSuffix_os_abi(self.os.tag, self.abi);1536 return linuxTripleSimple(allocator, target.cpu.arch, target.os.tag, target.abi);
1442}1537}
14431538
1444pub fn dynamicLibSuffix(self: Target) [:0]const u8 {1539pub fn exeFileExt(target: Target) [:0]const u8 {
1445 return self.os.tag.dynamicLibSuffix();1540 return target.os.tag.exeFileExt(target.cpu.arch);
1446}1541}
14471542
1448pub fn libPrefix_os_abi(os_tag: Os.Tag, abi: Abi) [:0]const u8 {1543pub fn staticLibSuffix(target: Target) [:0]const u8 {
1449 if (abi == .msvc) {1544 return target.os.tag.staticLibSuffix(target.abi);
1450 return "";
1451 }
1452 switch (os_tag) {
1453 .windows, .uefi => return "",
1454 else => return "lib",
1455 }
1456}1545}
14571546
1458pub fn libPrefix(self: Target) [:0]const u8 {1547pub fn dynamicLibSuffix(target: Target) [:0]const u8 {
1459 return libPrefix_os_abi(self.os.tag, self.abi);1548 return target.os.tag.dynamicLibSuffix();
1460}1549}
14611550
1462pub inline fn isMinGW(self: Target) bool {1551pub fn libPrefix(target: Target) [:0]const u8 {
1463 return self.os.tag == .windows and self.isGnu();1552 return target.os.tag.libPrefix(target.abi);
1464}1553}
14651554
1466pub inline fn isGnu(self: Target) bool {1555pub inline fn isMinGW(target: Target) bool {
1467 return self.abi.isGnu();1556 return target.os.tag == .windows and target.isGnu();
1468}1557}
14691558
1470pub inline fn isMusl(self: Target) bool {1559pub inline fn isGnu(target: Target) bool {
1471 return self.abi.isMusl();1560 return target.abi.isGnu();
1472}1561}
14731562
1474pub inline fn isAndroid(self: Target) bool {1563pub inline fn isMusl(target: Target) bool {
1475 return self.abi == .android;1564 return target.abi.isMusl();
1476}1565}
14771566
1478pub inline fn isWasm(self: Target) bool {1567pub inline fn isAndroid(target: Target) bool {
1479 return self.cpu.arch.isWasm();1568 return target.abi == .android;
1480}1569}
14811570
1482pub inline fn isDarwin(self: Target) bool {1571pub inline fn isWasm(target: Target) bool {
1483 return self.os.tag.isDarwin();1572 return target.cpu.arch.isWasm();
1484}1573}
14851574
1486pub inline fn isBSD(self: Target) bool {1575pub inline fn isDarwin(target: Target) bool {
1487 return self.os.tag.isBSD();1576 return target.os.tag.isDarwin();
1488}1577}
14891578
1490pub inline fn isBpfFreestanding(self: Target) bool {1579pub inline fn isBSD(target: Target) bool {
1491 return self.cpu.arch.isBpf() and self.os.tag == .freestanding;1580 return target.os.tag.isBSD();
1492}1581}
14931582
1494pub inline fn isGnuLibC_os_tag_abi(os_tag: Os.Tag, abi: Abi) bool {1583pub inline fn isBpfFreestanding(target: Target) bool {
1495 return os_tag == .linux and abi.isGnu();1584 return target.cpu.arch.isBpf() and target.os.tag == .freestanding;
1496}1585}
14971586
1498pub inline fn isGnuLibC(self: Target) bool {1587pub inline fn isGnuLibC(target: Target) bool {
1499 return isGnuLibC_os_tag_abi(self.os.tag, self.abi);1588 return target.os.tag.isGnuLibC(target.abi);
1500}1589}
15011590
1502pub inline fn supportsNewStackCall(self: Target) bool {1591pub inline fn supportsNewStackCall(target: Target) bool {
1503 return !self.cpu.arch.isWasm();1592 return !target.cpu.arch.isWasm();
1504}1593}
15051594
1506pub inline fn isSpirV(self: Target) bool {1595pub inline fn isSpirV(target: Target) bool {
1507 return self.cpu.arch.isSpirV();1596 return target.cpu.arch.isSpirV();
1508}1597}
15091598
1510pub const FloatAbi = enum {1599pub const FloatAbi = enum {
...@@ -1512,15 +1601,15 @@ pub const FloatAbi = enum {...@@ -1512,15 +1601,15 @@ pub const FloatAbi = enum {
1512 soft,1601 soft,
1513};1602};
15141603
1515pub inline fn getFloatAbi(self: Target) FloatAbi {1604pub inline fn getFloatAbi(target: Target) FloatAbi {
1516 return self.abi.floatAbi();1605 return target.abi.floatAbi();
1517}1606}
15181607
1519pub inline fn hasDynamicLinker(self: Target) bool {1608pub inline fn hasDynamicLinker(target: Target) bool {
1520 if (self.cpu.arch.isWasm()) {1609 if (target.cpu.arch.isWasm()) {
1521 return false;1610 return false;
1522 }1611 }
1523 switch (self.os.tag) {1612 switch (target.os.tag) {
1524 .freestanding,1613 .freestanding,
1525 .ios,1614 .ios,
1526 .tvos,1615 .tvos,
...@@ -1547,259 +1636,210 @@ pub const DynamicLinker = struct {...@@ -1547,259 +1636,210 @@ pub const DynamicLinker = struct {
15471636
1548 /// Used to construct the dynamic linker path. This field should not be used1637 /// Used to construct the dynamic linker path. This field should not be used
1549 /// directly. See `get` and `set`.1638 /// directly. See `get` and `set`.
1550 max_byte: ?u8,1639 len: u8,
15511640
1552 pub const none: DynamicLinker = .{1641 pub const none: DynamicLinker = .{ .buffer = undefined, .len = 0 };
1553 .buffer = undefined,
1554 .max_byte = null,
1555 };
15561642
1557 /// Asserts that the length is less than or equal to 255 bytes.1643 /// Asserts that the length is less than or equal to 255 bytes.
1558 pub fn init(dl_or_null: ?[]const u8) DynamicLinker {1644 pub fn init(maybe_path: ?[]const u8) DynamicLinker {
1559 var result: DynamicLinker = undefined;1645 var dl: DynamicLinker = undefined;
1560 result.set(dl_or_null);1646 dl.set(maybe_path);
1561 return result;1647 return dl;
1648 }
1649
1650 pub fn initFmt(comptime fmt_str: []const u8, args: anytype) !DynamicLinker {
1651 var dl: DynamicLinker = undefined;
1652 try dl.setFmt(fmt_str, args);
1653 return dl;
1562 }1654 }
15631655
1564 /// The returned memory has the same lifetime as the `DynamicLinker`.1656 /// The returned memory has the same lifetime as the `DynamicLinker`.
1565 pub fn get(self: *const DynamicLinker) ?[]const u8 {1657 pub fn get(dl: *const DynamicLinker) ?[]const u8 {
1566 const m: usize = self.max_byte orelse return null;1658 return if (dl.len > 0) dl.buffer[0..dl.len] else null;
1567 return self.buffer[0 .. m + 1];
1568 }1659 }
15691660
1570 /// Asserts that the length is less than or equal to 255 bytes.1661 /// Asserts that the length is less than or equal to 255 bytes.
1571 pub fn set(self: *DynamicLinker, dl_or_null: ?[]const u8) void {1662 pub fn set(dl: *DynamicLinker, maybe_path: ?[]const u8) void {
1572 if (dl_or_null) |dl| {1663 const path = maybe_path orelse "";
1573 @memcpy(self.buffer[0..dl.len], dl);1664 @memcpy(dl.buffer[0..path.len], path);
1574 self.max_byte = @intCast(dl.len - 1);1665 dl.len = @intCast(path.len);
1575 } else {
1576 self.max_byte = null;
1577 }
1578 }1666 }
15791667
1580 pub fn eql(a: DynamicLinker, b: DynamicLinker) bool {1668 /// 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;1669 pub fn setFmt(dl: *DynamicLinker, comptime fmt_str: []const u8, args: anytype) !void {
1582 const b_m = b.max_byte orelse return false;1670 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 }1671 }
1588};
1589
1590pub fn standardDynamicLinkerPath(target: Target) DynamicLinker {
1591 return standardDynamicLinkerPath_cpu_os_abi(target.cpu, target.os.tag, target.abi);
1592}
15931672
1594pub fn standardDynamicLinkerPath_cpu_os_abi(cpu: Cpu, os_tag: Os.Tag, abi: Abi) DynamicLinker {1673 pub fn eql(lhs: DynamicLinker, rhs: DynamicLinker) bool {
1595 var result = DynamicLinker.none;1674 return std.mem.eql(u8, lhs.buffer[0..lhs.len], rhs.buffer[0..rhs.len]);
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 }1675 }
16141676
1615 if (abi.isMusl()) {1677 pub fn standard(cpu: Cpu, os_tag: Os.Tag, abi: Abi) DynamicLinker {
1616 const is_arm = switch (cpu.arch) {1678 return if (abi == .android) initFmt("/system/bin/linker{s}", .{
1617 .arm, .armeb, .thumb, .thumbeb => true,1679 if (ptrBitWidth_cpu_abi(cpu, abi) == 64) "64" else "",
1618 else => false,1680 }) catch unreachable else if (abi.isMusl()) return initFmt("/lib/ld-musl-{s}{s}.so.1", .{
1619 };1681 @tagName(switch (cpu.arch) {
1620 const arch_part = switch (cpu.arch) {1682 .thumb => .arm,
1621 .arm, .thumb => "arm",1683 .thumbeb => .armeb,
1622 .armeb, .thumbeb => "armeb",1684 else => cpu.arch,
1623 else => |arch| @tagName(arch),1685 }),
1624 };1686 if (cpu.arch.isArmOrThumb() and abi.floatAbi() == .hard) "hf" else "",
1625 const arch_suffix = if (is_arm and abi.floatAbi() == .hard) "hf" else "";1687 }) catch unreachable else switch (os_tag) {
1626 return print(&result, "/lib/ld-musl-{s}{s}.so.1", .{ arch_part, arch_suffix });1688 .freebsd => init("/libexec/ld-elf.so.1"),
1627 }1689 .netbsd => init("/libexec/ld.elf_so"),
1690 .openbsd => init("/usr/libexec/ld.so"),
1691 .dragonfly => init("/libexec/ld-elf.so.2"),
1692 .solaris, .illumos => init("/lib/64/ld.so.1"),
1693 .linux => switch (cpu.arch) {
1694 .x86,
1695 .sparc,
1696 .sparcel,
1697 => init("/lib/ld-linux.so.2"),
16281698
1629 switch (os_tag) {1699 .aarch64 => init("/lib/ld-linux-aarch64.so.1"),
1630 .freebsd => return copy(&result, "/libexec/ld-elf.so.1"),1700 .aarch64_be => init("/lib/ld-linux-aarch64_be.so.1"),
1631 .netbsd => return copy(&result, "/libexec/ld.elf_so"),1701 .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"),
16401702
1641 .aarch64 => return copy(&result, "/lib/ld-linux-aarch64.so.1"),1703 .arm,
1642 .aarch64_be => return copy(&result, "/lib/ld-linux-aarch64_be.so.1"),1704 .armeb,
1643 .aarch64_32 => return copy(&result, "/lib/ld-linux-aarch64_32.so.1"),1705 .thumb,
1706 .thumbeb,
1707 => initFmt("/lib/ld-linux{s}.so.3", .{switch (abi.floatAbi()) {
1708 .hard => "-armhf",
1709 else => "",
1710 }}) catch unreachable,
16441711
1645 .arm,1712 .mips,
1646 .armeb,1713 .mipsel,
1647 .thumb,1714 .mips64,
1648 .thumbeb,1715 .mips64el,
1649 => return copy(&result, switch (abi.floatAbi()) {1716 => initFmt("/lib{s}/{s}", .{
1650 .hard => "/lib/ld-linux-armhf.so.3",1717 switch (abi) {
1651 else => "/lib/ld-linux.so.3",1718 .gnuabin32, .gnux32 => "32",
1652 }),1719 .gnuabi64 => "64",
1720 else => "",
1721 },
1722 if (mips.featureSetHas(cpu.features, .nan2008))
1723 "ld-linux-mipsn8.so.1"
1724 else
1725 "ld.so.1",
1726 }) catch unreachable,
1727
1728 .powerpc, .powerpcle => init("/lib/ld.so.1"),
1729 .powerpc64, .powerpc64le => init("/lib64/ld64.so.2"),
1730 .s390x => init("/lib64/ld64.so.1"),
1731 .sparc64 => init("/lib64/ld-linux.so.2"),
1732 .x86_64 => init(switch (abi) {
1733 .gnux32 => "/libx32/ld-linux-x32.so.2",
1734 else => "/lib64/ld-linux-x86-64.so.2",
1735 }),
1736
1737 .riscv32 => init("/lib/ld-linux-riscv32-ilp32.so.1"),
1738 .riscv64 => init("/lib/ld-linux-riscv64-lp64.so.1"),
1739
1740 // Architectures in this list have been verified as not having a standard
1741 // dynamic linker path.
1742 .wasm32,
1743 .wasm64,
1744 .bpfel,
1745 .bpfeb,
1746 .nvptx,
1747 .nvptx64,
1748 .spu_2,
1749 .avr,
1750 .spirv32,
1751 .spirv64,
1752 => none,
16531753
1654 .mips,1754 // TODO go over each item in this list and either move it to the above list, or
1655 .mipsel,1755 // implement the standard dynamic linker path code for it.
1656 .mips64,1756 .arc,
1657 .mips64el,1757 .csky,
1658 => {1758 .hexagon,
1659 const lib_suffix = switch (abi) {1759 .m68k,
1660 .gnuabin32, .gnux32 => "32",1760 .msp430,
1661 .gnuabi64 => "64",1761 .r600,
1662 else => "",1762 .amdgcn,
1663 };1763 .tce,
1664 const is_nan_2008 = mips.featureSetHas(cpu.features, .nan2008);1764 .tcele,
1665 const loader = if (is_nan_2008) "ld-linux-mipsn8.so.1" else "ld.so.1";1765 .xcore,
1666 return print(&result, "/lib{s}/{s}", .{ lib_suffix, loader });1766 .le32,
1767 .le64,
1768 .amdil,
1769 .amdil64,
1770 .hsail,
1771 .hsail64,
1772 .spir,
1773 .spir64,
1774 .kalimba,
1775 .shave,
1776 .lanai,
1777 .renderscript32,
1778 .renderscript64,
1779 .ve,
1780 .dxil,
1781 .loongarch32,
1782 .loongarch64,
1783 .xtensa,
1784 => none,
1667 },1785 },
16681786
1669 .powerpc, .powerpcle => return copy(&result, "/lib/ld.so.1"),1787 .ios,
1670 .powerpc64, .powerpc64le => return copy(&result, "/lib64/ld64.so.2"),1788 .tvos,
1671 .s390x => return copy(&result, "/lib64/ld64.so.1"),1789 .watchos,
1672 .sparc64 => return copy(&result, "/lib64/ld-linux.so.2"),1790 .macos,
1673 .x86_64 => return copy(&result, switch (abi) {1791 => 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"),
16801792
1681 // Architectures in this list have been verified as not having a standard1793 // Operating systems in this list have been verified as not having a standard
1682 // dynamic linker path.1794 // dynamic linker path.
1683 .wasm32,1795 .freestanding,
1684 .wasm64,1796 .uefi,
1685 .bpfel,1797 .windows,
1686 .bpfeb,1798 .emscripten,
1687 .nvptx,1799 .wasi,
1688 .nvptx64,1800 .opencl,
1689 .spu_2,1801 .glsl450,
1690 .avr,1802 .vulkan,
1691 .spirv32,1803 .other,
1692 .spirv64,1804 .plan9,
1693 => return result,1805 => none,
1806
1807 // TODO revisit when multi-arch for Haiku is available
1808 .haiku => init("/system/runtime_loader"),
16941809
1695 // TODO go over each item in this list and either move it to the above list, or1810 // 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.1811 // implement the standard dynamic linker path code for it.
1697 .arc,1812 .ananas,
1698 .csky,1813 .cloudabi,
1699 .hexagon,1814 .fuchsia,
1700 .m68k,1815 .kfreebsd,
1701 .msp430,1816 .lv2,
1702 .r600,1817 .zos,
1703 .amdgcn,1818 .minix,
1704 .tce,1819 .rtems,
1705 .tcele,1820 .nacl,
1706 .xcore,1821 .aix,
1707 .le32,1822 .cuda,
1708 .le64,1823 .nvcl,
1709 .amdil,1824 .amdhsa,
1710 .amdil64,1825 .ps4,
1711 .hsail,1826 .ps5,
1712 .hsail64,1827 .elfiamcu,
1713 .spir,1828 .mesa3d,
1714 .spir64,1829 .contiki,
1715 .kalimba,1830 .amdpal,
1716 .shave,1831 .hermit,
1717 .lanai,1832 .hurd,
1718 .renderscript32,1833 .driverkit,
1719 .renderscript64,1834 .shadermodel,
1720 .ve,1835 .liteos,
1721 .dxil,1836 => none,
1722 .loongarch32,1837 };
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 }1838 }
1779}1839};
17801840
1781/// 0c spim little-endian MIPS 3000 family1841pub fn standardDynamicLinkerPath(target: Target) DynamicLinker {
1782/// 1c 68000 Motorola MC680001842 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}1843}
18041844
1805pub fn maxIntAlignment(target: Target) u16 {1845pub fn maxIntAlignment(target: Target) u16 {
...@@ -2076,7 +2116,7 @@ pub fn c_type_byte_size(t: Target, c_type: CType) u16 {...@@ -2076,7 +2116,7 @@ pub fn c_type_byte_size(t: Target, c_type: CType) u16 {
2076 16 => 2,2116 16 => 2,
2077 32 => 4,2117 32 => 4,
2078 64 => 8,2118 64 => 8,
2079 80 => @as(u16, @intCast(std.mem.alignForward(usize, 10, c_type_alignment(t, .longdouble)))),2119 80 => @intCast(std.mem.alignForward(usize, 10, c_type_alignment(t, .longdouble))),
2080 128 => 16,2120 128 => 16,
2081 else => unreachable,2121 else => unreachable,
2082 },2122 },
...@@ -2419,7 +2459,7 @@ pub fn c_type_alignment(target: Target, c_type: CType) u16 {...@@ -2419,7 +2459,7 @@ pub fn c_type_alignment(target: Target, c_type: CType) u16 {
2419 // Next-power-of-two-aligned, up to a maximum.2459 // Next-power-of-two-aligned, up to a maximum.
2420 return @min(2460 return @min(
2421 std.math.ceilPowerOfTwoAssert(u16, (c_type_bit_size(target, c_type) + 7) / 8),2461 std.math.ceilPowerOfTwoAssert(u16, (c_type_bit_size(target, c_type) + 7) / 8),
2422 switch (target.cpu.arch) {2462 @as(u16, switch (target.cpu.arch) {
2423 .arm, .armeb, .thumb, .thumbeb => switch (target.os.tag) {2463 .arm, .armeb, .thumb, .thumbeb => switch (target.os.tag) {
2424 .netbsd => switch (target.abi) {2464 .netbsd => switch (target.abi) {
2425 .gnueabi,2465 .gnueabi,
...@@ -2431,7 +2471,7 @@ pub fn c_type_alignment(target: Target, c_type: CType) u16 {...@@ -2431,7 +2471,7 @@ pub fn c_type_alignment(target: Target, c_type: CType) u16 {
2431 .musleabihf,2471 .musleabihf,
2432 => 8,2472 => 8,
24332473
2434 else => @as(u16, 4),2474 else => 4,
2435 },2475 },
2436 .ios, .tvos, .watchos => 4,2476 .ios, .tvos, .watchos => 4,
2437 else => 8,2477 else => 8,
...@@ -2501,7 +2541,7 @@ pub fn c_type_alignment(target: Target, c_type: CType) u16 {...@@ -2501,7 +2541,7 @@ pub fn c_type_alignment(target: Target, c_type: CType) u16 {
2501 .wasm32,2541 .wasm32,
2502 .wasm64,2542 .wasm64,
2503 => 16,2543 => 16,
2504 },2544 }),
2505 );2545 );
2506}2546}
25072547
...@@ -2559,8 +2599,8 @@ pub fn c_type_preferred_alignment(target: Target, c_type: CType) u16 {...@@ -2559,8 +2599,8 @@ pub fn c_type_preferred_alignment(target: Target, c_type: CType) u16 {
2559 // Next-power-of-two-aligned, up to a maximum.2599 // Next-power-of-two-aligned, up to a maximum.
2560 return @min(2600 return @min(
2561 std.math.ceilPowerOfTwoAssert(u16, (c_type_bit_size(target, c_type) + 7) / 8),2601 std.math.ceilPowerOfTwoAssert(u16, (c_type_bit_size(target, c_type) + 7) / 8),
2562 switch (target.cpu.arch) {2602 @as(u16, switch (target.cpu.arch) {
2563 .msp430 => @as(u16, 2),2603 .msp430 => 2,
25642604
2565 .csky,2605 .csky,
2566 .xcore,2606 .xcore,
...@@ -2627,7 +2667,7 @@ pub fn c_type_preferred_alignment(target: Target, c_type: CType) u16 {...@@ -2627,7 +2667,7 @@ pub fn c_type_preferred_alignment(target: Target, c_type: CType) u16 {
2627 .wasm32,2667 .wasm32,
2628 .wasm64,2668 .wasm64,
2629 => 16,2669 => 16,
2630 },2670 }),
2631 );2671 );
2632}2672}
26332673
...@@ -2767,19 +2807,7 @@ fn eqlIgnoreCase(ignore_case: bool, a: []const u8, b: []const u8) bool {...@@ -2767,19 +2807,7 @@ fn eqlIgnoreCase(ignore_case: bool, a: []const u8, b: []const u8) bool {
2767}2807}
27682808
2769pub fn osArchName(target: std.Target) [:0]const u8 {2809pub fn osArchName(target: std.Target) [:0]const u8 {
2770 return switch (target.os.tag) {2810 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}2811}
27842812
2785const Target = @This();2813const 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 \\};